【4.1】Ribbon负载均衡
- 1 Ribbon--负载均衡原理
- 1.1 负载均衡流程
- 1.2 源码分析(debug)
- 2 总结
1 Ribbon–负载均衡原理
1.1 负载均衡流程
图中的地址是真实可用的地址吗?
显然不是。
这样一个请求实际上是无法直接到达user-service的。
因此中间一定会有“人”将这个请求拦下并做一些处理。
“这个人就是”Ribbon
Ribbon在拦截下请求之后,要想办法找到真实的地址。它首先要知道这个请求指定的是哪个服务,然后去找eureka-server拉取userservice,然后eureka-server返回服务列表。
然后就挑选到具体的user-service:
1.2 源码分析(debug)
打开OrderApplication.java:
@LoadBalanced注解就是一个标记,标记将来RestTemplate发起的请求要被Ribbon去拦截和处理。
那么拦截的动作是谁去完成的呢?
这里我的快捷键是双击 /
找到下图的类,打开:
可以看到它实现了一个接口,叫做ClientHttpRequestInterceptor ,它会去拦截由客户端发起的http请求。RestTemplate正是一个发起http请求的客户端,所以就会被拦截。
这个接口的方法名叫intercept。
回到LoadBalancerInterceptor.java,可以看到实现了这个方法:
在图上位置打个断点,回浏览器去发起请求:
回到idea:
可以看到这个请求确实被拦截了,拦截之后做什么呢?
可以看到 request.getURI (),也就是获取请求地址。
再走一步:
originalUri.getHost()也就是获得主机名
再往下走:
可以看到它拿到了服务名称userservice,接下来就是去找Eureka完成服务的拉取。
然后可以看到这里将获取的serviceName交给了loadBalancer去执行。
loadBalancer又是什么呢?看图:
它是一个RibbonLoadBanlancerClient对象。
接下来我们跟入这个方法:
可以看到执行完成之后得到一个loadBalancer对象,右下角看到这个对象的名字叫做
DynamicServerListLoadBalancer动态服务列表负载均衡器
然后展开可以看到:
ServerList也就是服务列表。可以看到8081和8082已经被成功的拉取到了。
所以由此可知上面代码中的:
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
就是在根据服务名称找eureka拉取服务列表。
此时服务列表已经拿到,下一步就是做负载均衡。
图中打断点这行:
Server server = this.getServer(loadBalancer, hint);
上面图中显示了loadBalancer中有一个ServerList,这里getServer取出一个。
再跟进这个方法:
发现它调用了chooseServer这个方法,再跟进去:
发现他去找super.chooseServer,再跟进去:
可以看到这里有个rule.choose(key);
rule也就是规则的意思,相当于现在要从DynamicServerList中选一个,需要一种规则。
接下来看一下这个rule是什么类型的对象:
可以看到它是一个IRule类,I代表接口,Rule代表规则,也就是说它是一个规则的接口,接下来用ctrl+H查看它的实现类:
RandomRule–随机
RoundRobinRule–轮询
而默认的负载规则是:ZoneAvoidanceRule:
基于分区下的服务器的可用性选出可用分区列表,再从可用分区列表中随机选择一个分区,采用轮询的策略选择该分区的一个服务器。
然后继续往下:
可以看到拿到了8081。
拿到地址信息了,下一步就可以根据真实的ip地址和端口号来替代原来的服务名称去发起真实请求。
2 总结
当请求进入Ribbon之后,Ribbon会怎么去处理呢?
首先,请求会被一个拦截器拦住, 这个拦截器的名字叫做LoadBalancerInterceptor负载均衡拦截器。
它拦截下来以后会得到请求中的服务名称,然后把它交给 RibbonLoadBanlancerClient。
而RibbonLoadBanlancerClient又会将服务交给 DynamicServerListLoadBalancer
然后DynamicServerListLoadBalancer又会去eureka-server里拉取服务列表;
之后,DynamicServerListLoadBalancer会去找 IRule;
而IRule会基于规则选择某个服务,并将选中的服务返回给RibbonLoadBanlancerClient。
然后RibbonLoadBanlancerClient就会用得到的真实的ip和端口替换服务名称,得到真实的请求地址然后就去完成请求。
这就是整个Ribbon工作的流程。
By --Suki 2023/1/4
知识内容来自于黑马程序员视频教学和百度百科。博主仅作笔记整理便于回顾学习。如有侵权请私信我。