介绍
ReactiveLoadBalancerClientFilter是Springcloud中的一个重要的过滤器, 主要用于实现负载均衡, 将客户端的请求路由到不同的后端实例上来实现负载均衡和高可用
使用
spring:
cloud:
gateway:
routes:
- id: my-route
uri: lb://my-service # 前缀'lb://'代表开启负载均衡
predicates:
- Path=/my-path/**
关键代码
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
这个方法主要作用是使用负载均衡客户端选取后端服务实例, 构建目标URL并存储在ServerWebExchange中
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
if (url == null
|| (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
return chain.filter(exchange);
}
// preserve the original url
addOriginalRequestUrl(exchange, url);
if (log.isTraceEnabled()) {
log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName()
+ " url before: " + url);
}
return choose(exchange).doOnNext(response -> {
// 使用doOnNext处理choose方法返回的ServiceInstance实例
if (!response.hasServer()) {
throw NotFoundException.create(properties.isUse404(),
"Unable to find instance for " + url.getHost());
}
ServiceInstance retrievedInstance = response.getServer();
URI uri = exchange.getRequest().getURI();
// if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
// if the loadbalancer doesn't provide one.
// 确定协议
String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";
if (schemePrefix != null) {
overrideScheme = url.getScheme();
}
// 创建一个DelegatingServiceInstance 实例, 该实例包装了选定的ServiceInstance并指定了协议
DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(
retrievedInstance, overrideScheme);
// 使用DelegatingServiceInstance 实例和原始URI来构建目标请求的URI
URI requestUrl = reconstructURI(serviceInstance, uri);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
}
// 将构建的目标请求URI存储到ServerWebExchange的属性中提供给后续的过滤器
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
}).then(chain.filter(exchange));
}