Ribbon负载均衡源码探究:
假设当前有一个订单服务,以及一个用户服务,用户服务为分布式架构,探究Ribbon中是如何实现负载均衡。
源码探究:
1、双击shift搜索类,查找LoadBalancerInterceptor注意在cloud包下面的才是。
2、在这个类中我们发现这个类实现了一个接口ClientHttpRequestInterceptor,继续跟进发现这个接口中只有一个方法intercept。那么肯定实现了这个方法。
3、返回LoadBalancerInterceptor,找到intercept这个方法.开启调试,看看能不能获取到地址。
4、果不其然,在浏览器的地址被他获取到了。看看他到底是怎么解析,怎么进行负载均衡,至于怎么获取到的不是今天的主题,所以我们往下执行,excute是执行的意思,见名之意继续跟进。
5、继续跟进,在这里我们可以看到servername被当作serverId传递进来。
getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。
如下图:
getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8081端口的服务
6、那到底是怎么根据负载均衡获取的呢,因为刚刚是getServer获取到的服务地址,那我们跟进getServer。
第一个if判断是false所以走的是chooseServer(),继续跟进。
7、在这里我们发现调用了super.chooseServer,这是调用父辈的方法吗,我们继续跟进。
继续跟进。
8、跟进到父辈方法的chooseServer中我们发现,这里有一个rule.choose( ) 见名之意,规则、选择,难道就是这里吗?
9、转到rule看看,是一个接口,默认是RoundRobinRule
查看IRule的实现类,又是见名之意,随机规则,轮询规则…等等。
10、聪明的小伙伴估计一下就看出来了,刚刚在父辈类中,IRule默认是RoundRobinRule,所以真相大白。果然实现了负载均衡啊。
总结:
- 拦截我们的RestTemplate请求http://userservice/user/4
- RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
- DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
- eureka返回列表,localhost:8081、localhost:8082
- IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
- RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/4,发起真实请求