文章26 | 阅读 10674 | 点赞0
本文主要分享 LoadBalancerClientFilter 的代码实现。
LoadBalancerClientFilter 根据 lb://
前缀过滤处理,使用 serviceId
选择一个服务实例,从而实现负载均衡。
在 《Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注册中心》「2. 环境搭建」 有详细教程。
org.springframework.cloud.gateway.filter.LoadBalancerClientFilter
,代码如下 :
1: public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
2:
3: private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class);
4: public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100;
5:
6: private final LoadBalancerClient loadBalancer;
7:
8: public LoadBalancerClientFilter(LoadBalancerClient loadBalancer) {
9: this.loadBalancer = loadBalancer;
10: }
11:
12: @Override
13: public int getOrder() {
14: return LOAD_BALANCER_CLIENT_FILTER_ORDER;
15: }
16:
17: @Override
18: public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
19: // 获得 URL
20: URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
21: if (url == null || !url.getScheme().equals("lb")) {
22: return chain.filter(exchange);
23: }
24: // 添加 原始请求URI 到 GATEWAY_ORIGINAL_REQUEST_URL_ATTR
25: //preserve the original url
26: addOriginalRequestUrl(exchange, url);
27:
28: log.trace("LoadBalancerClientFilter url before: " + url);
29:
30: // 获取 服务实例
31: final ServiceInstance instance = loadBalancer.choose(url.getHost());
32: if (instance == null) {
33: throw new NotFoundException("Unable to find instance for " + url.getHost());
34: }
35:
36: /*URI uri = exchange.getRequest().getURI();
37: URI requestUrl = loadBalancer.reconstructURI(instance, uri);*/
38: //
39: URI requestUrl = UriComponentsBuilder.fromUri(url)
40: .scheme(instance.isSecure()? "https" : "http") //TODO: support websockets
41: .host(instance.getHost())
42: .port(instance.getPort())
43: .build(true)
44: .toUri();
45: log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
46:
47: // 添加 请求URI 到 GATEWAY_REQUEST_URL_ATTR
48: exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
49:
50: // 提交过滤器链继续过滤
51: return chain.filter(exchange);
52: }
53:
54: }
lb://
为前缀( Scheme )的地址。ServerWebExchangeUtils#addOriginalRequestUrl(...)
添加原始请求 URI 到 GATEWAY_ORIGINAL_REQUEST_URL_ATTR
。代码如下 :public static void addOriginalRequestUrl(ServerWebExchange exchange, URI url) {
exchange.getAttributes().computeIfAbsent(GATEWAY_ORIGINAL_REQUEST_URL_ATTR, s -> new LinkedHashSet<>()); // 数组,考虑多次重写
LinkedHashSet<URI> uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
uris.add(url);
}
第 30 至 34 行 :调用 LoadBalancerClient#choose(String)
方法,获得一个服务实例( ServiceInstance ) ,从而实现负载均衡。
熟悉 Spring Cloud 的同学都知道,一般情况下 LoadBalancerClient 实现类为 org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
。
举个 instance
的值例子 :
第 39 至 45 行 :创建 requestUrl
。举个例子 :
第 48 行 :设置 requestUrl
到 GATEWAY_REQUEST_URL_ATTR
。后面 Routing 相关的 GatewayFilter 会通过该属性,发起请求。
第 51 行 :提交过滤器链继续过滤。注意,这里不需要创建新的 ServerWebExchange
我们回过头看 《Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注册中心》「4. 高能」
相同服务( serviceId
相同) ,服务实例的注册或下线,Ribbon 已经处理,所以不用担心。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_42073629/article/details/106934507
内容来源于网络,如有侵权,请联系作者删除!