SpringCloud Ribbon负载均衡技术

我们在spring-cloud中要使用ribbon做负载均衡的时候一般会添加如下包:

并在@Configuration的javaconfig配置中配置如下restTemplate,加上注解@LoadBalanced则实现了前端负载均衡。

下面看看Ribbon的原理:

核心为org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient类:


LoadBalancerClient的实现类为RibbonLoadBalancerClient,这个类是非常重要的一个类,最终的负载均衡的请求处理,由它来执行。

RibbonLoadBalancerClient的核心方法如下:


可知,LoadBalancerClient的选择服务器实例的方法最终是由ILoadBalancer的chooseServer来实现。

ILoadBalancer的实现类为com.netflix.loadbalancer.DynamicServerListLoadBalancer:


其中其核心的属性为IRule和Iping

IRule有很多默认的实现类,这些实现类根据不同的算法和逻辑来处理负载均衡。Ribbon实现的IRule有一下。在大多数情况下,这些默认的实现类是可以满足需求的,如果有特性的需求,可以自己实现。

BestAvailableRule 选择最小请求数

ClientConfigEnabledRoundRobinRule 轮询

RandomRule 随机选择一个server

RoundRobinRule 轮询选择server

RetryRule 根据轮询的方式重试

WeightedResponseTimeRule 根据响应时间去分配一个weight ,weight越低,被选择的可能性就越低

ZoneAvoidanceRule 根据server的zone区域和可用性来轮询选择。


IPing是用来想server发生”ping”,来判断该server是否有响应,从而判断该server是否可用。


PingUrl 真实的去ping 某个url,判断其是否alive

PingConstant 固定返回某服务是否可用,默认返回true,即可用

NoOpPing 不去ping,直接返回true,即可用。

DummyPing 直接返回true,并实现了initWithNiwsConfig方法。

NIWSDiscoveryPing,根据DiscoveryEnabledServer的InstanceInfo的InstanceStatus去判断,如果为InstanceStatus.UP,则为可用,否则不可用。

在DynamicServerListLoadBalancer的构造函数中会调用initWithNiwsConfig,配置相应的IRule和Iping的属性,并调用了restOfInit()方法:



serverListImpl的实现类为com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList类,查看getUpdatedListOfServers()方法:


    其中eurekaClientProvider的实现类是LegacyEurekaClientProvider,它是一个获取eurekaClient类,通过加锁的实例方法去获取eurekaClient,其代码如下:


urekaClient的实现类为DiscoveryClient,由此可见,负载均衡器是从EurekaClient获取服务信息,并根据IRule去路由,并且根据IPing去判断服务的可用性。

负载均衡器多久会同步Eureka的注册列表数据呢?

回到最初的DynamicServerListLoadBalancer构造器中,实例化的时候调用了BaseLoadBalancer的构造方法开启了一个PingTask任务,代码如下:



setupPingTask()的具体代码逻辑,它开启了ShutdownEnabledTimer执行PingTask任务,在默认情况下pingIntervalSeconds为10,即每10秒钟,想EurekaClient发送一次”ping”。




查看Pinger的runPinger()方法,最终根据 pingerStrategy.pingServers(ping, allServers)来获取服务的可用性,如果该返回结果,如之前相同,则不去向EurekaClient获取注册列表,如果不同则通知ServerStatusChangeListener或者changeListeners发生了改变,进行更新或者重新拉取。

由此可见,LoadBalancerClient是在初始化的时候,会向EurekaClient拉取服务注册列表,并且向通过10s一次向EurekaClient发送“ping”,来判断服务的可用性,如果服务的可用性发生了改变或者服务数量和之前的不一致,则更新或者重新拉取。LoadBalancerClient有了这些服务注册列表,就可以根据具体的IRule来进行负载均衡。

RestTempalate与Ribbon结合


在该类中,首先维护了一个被@LoadBalanced修饰的RestTemplate对象的List,在初始化的过程中,通过调用customizer.customize(restTemplate)方法来给RestTemplate增加拦截器LoadBalancerInterceptor。


而LoadBalancerInterceptor,用于实时拦截,在LoadBalancerInterceptor这里实现来负载均衡。LoadBalancerInterceptor的拦截方法如下:


查看RibbonLoadBalancerClient的execute方法:


最终由IRule的策略选取实例。

综上所述,Ribbon的负载均衡,主要通过LoadBalancerClient来实现的,而LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等信息,并向EurekaClient获取注册列表的信息,并默认10秒一次向EurekaClient发送“ping”,进而检查是否更新服务列表,最后,得到注册列表后,ILoadBalancer根据IRule的策略进行负载均衡。

而RestTemplate 被@LoadBalanced注解后,能过用负载均衡,主要是维护了一个被@LoadBalance注解的RestTemplate列表,并给列表中的RestTemplate添加拦截器,进而交给负载均衡器去处理。

参考:https://blog.csdn.net/forezp/article/details/74820899

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容