SpringCloud Ribbon負載均衡技術(shù)

我們在spring-cloud中要使用ribbon做負載均衡的時候一般會添加如下包:

并在@Configuration的javaconfig配置中配置如下restTemplate,加上注解@LoadBalanced則實現(xiàn)了前端負載均衡。

下面看看Ribbon的原理:

核心為org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient類:


LoadBalancerClient的實現(xiàn)類為RibbonLoadBalancerClient,這個類是非常重要的一個類,最終的負載均衡的請求處理,由它來執(zhí)行。

RibbonLoadBalancerClient的核心方法如下:


可知,LoadBalancerClient的選擇服務(wù)器實例的方法最終是由ILoadBalancer的chooseServer來實現(xiàn)。

ILoadBalancer的實現(xiàn)類為com.netflix.loadbalancer.DynamicServerListLoadBalancer:


其中其核心的屬性為IRule和Iping

IRule有很多默認的實現(xiàn)類,這些實現(xiàn)類根據(jù)不同的算法和邏輯來處理負載均衡。Ribbon實現(xiàn)的IRule有一下。在大多數(shù)情況下,這些默認的實現(xiàn)類是可以滿足需求的,如果有特性的需求,可以自己實現(xiàn)。

BestAvailableRule 選擇最小請求數(shù)

ClientConfigEnabledRoundRobinRule 輪詢

RandomRule 隨機選擇一個server

RoundRobinRule 輪詢選擇server

RetryRule 根據(jù)輪詢的方式重試

WeightedResponseTimeRule 根據(jù)響應(yīng)時間去分配一個weight ,weight越低,被選擇的可能性就越低

ZoneAvoidanceRule 根據(jù)server的zone區(qū)域和可用性來輪詢選擇。


IPing是用來想server發(fā)生”ping”,來判斷該server是否有響應(yīng),從而判斷該server是否可用。


PingUrl 真實的去ping 某個url,判斷其是否alive

PingConstant 固定返回某服務(wù)是否可用,默認返回true,即可用

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

DummyPing 直接返回true,并實現(xiàn)了initWithNiwsConfig方法。

NIWSDiscoveryPing,根據(jù)DiscoveryEnabledServer的InstanceInfo的InstanceStatus去判斷,如果為InstanceStatus.UP,則為可用,否則不可用。

在DynamicServerListLoadBalancer的構(gòu)造函數(shù)中會調(diào)用initWithNiwsConfig,配置相應(yīng)的IRule和Iping的屬性,并調(diào)用了restOfInit()方法:



serverListImpl的實現(xiàn)類為com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList類,查看getUpdatedListOfServers()方法:


? ??其中eurekaClientProvider的實現(xiàn)類是LegacyEurekaClientProvider,它是一個獲取eurekaClient類,通過加鎖的實例方法去獲取eurekaClient,其代碼如下:


urekaClient的實現(xiàn)類為DiscoveryClient,由此可見,負載均衡器是從EurekaClient獲取服務(wù)信息,并根據(jù)IRule去路由,并且根據(jù)IPing去判斷服務(wù)的可用性。

負載均衡器多久會同步Eureka的注冊列表數(shù)據(jù)呢?

回到最初的DynamicServerListLoadBalancer構(gòu)造器中,實例化的時候調(diào)用了BaseLoadBalancer的構(gòu)造方法開啟了一個PingTask任務(wù),代碼如下:



setupPingTask()的具體代碼邏輯,它開啟了ShutdownEnabledTimer執(zhí)行PingTask任務(wù),在默認情況下pingIntervalSeconds為10,即每10秒鐘,想EurekaClient發(fā)送一次”ping”。




查看Pinger的runPinger()方法,最終根據(jù) pingerStrategy.pingServers(ping, allServers)來獲取服務(wù)的可用性,如果該返回結(jié)果,如之前相同,則不去向EurekaClient獲取注冊列表,如果不同則通知ServerStatusChangeListener或者changeListeners發(fā)生了改變,進行更新或者重新拉取。

由此可見,LoadBalancerClient是在初始化的時候,會向EurekaClient拉取服務(wù)注冊列表,并且向通過10s一次向EurekaClient發(fā)送“ping”,來判斷服務(wù)的可用性,如果服務(wù)的可用性發(fā)生了改變或者服務(wù)數(shù)量和之前的不一致,則更新或者重新拉取。LoadBalancerClient有了這些服務(wù)注冊列表,就可以根據(jù)具體的IRule來進行負載均衡。

RestTempalate與Ribbon結(jié)合


在該類中,首先維護了一個被@LoadBalanced修飾的RestTemplate對象的List,在初始化的過程中,通過調(diào)用customizer.customize(restTemplate)方法來給RestTemplate增加攔截器LoadBalancerInterceptor。


而LoadBalancerInterceptor,用于實時攔截,在LoadBalancerInterceptor這里實現(xiàn)來負載均衡。LoadBalancerInterceptor的攔截方法如下:


查看RibbonLoadBalancerClient的execute方法:


最終由IRule的策略選取實例。

綜上所述,Ribbon的負載均衡,主要通過LoadBalancerClient來實現(xiàn)的,而LoadBalancerClient具體交給了ILoadBalancer來處理,ILoadBalancer通過配置IRule、IPing等信息,并向EurekaClient獲取注冊列表的信息,并默認10秒一次向EurekaClient發(fā)送“ping”,進而檢查是否更新服務(wù)列表,最后,得到注冊列表后,ILoadBalancer根據(jù)IRule的策略進行負載均衡。

而RestTemplate 被@LoadBalanced注解后,能過用負載均衡,主要是維護了一個被@LoadBalance注解的RestTemplate列表,并給列表中的RestTemplate添加攔截器,進而交給負載均衡器去處理。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容