【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
知识内容来自于黑马程序员视频教学和百度百科。博主仅作笔记整理便于回顾学习。如有侵权请私信我。












![P1044 [NOIP2003 普及组] 栈](https://img-blog.csdnimg.cn/1f9c8b467efc402eb13e37b2cfa94c28.png)






