教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

Ribbon工作原理詳細(xì)介紹

更新時(shí)間:2020年11月19日17時(shí)51分 來源:傳智播客 瀏覽次數(shù):

好口碑IT培訓(xùn)

前面我們使用Ribbon實(shí)現(xiàn)負(fù)載均衡時(shí),基本用法是注入一個(gè)RestTemplate,并使用@LoadBalanced注解標(biāo)注RestTemplate,從而使RestTemplate具備負(fù)載均衡的能力。

當(dāng)Spring容器啟動(dòng)時(shí),使用@LoadBalanced注解修飾的RestTemplate會(huì)被添加攔截器,攔截器中使用了LoadBalancerClient處理請(qǐng)求,從而達(dá)到負(fù)載均衡的目的。那么LoadBalancerClient內(nèi)部是如何做到的呢?下面我們通過源碼分析的方式來剖析Ribbon負(fù)載均衡的工作原理。

LoadBalancerClient是Spring Cloud提供的一個(gè)非常重要的接口,它繼承自ServiceInstanceChooser接口,該接口的實(shí)現(xiàn)類是RibbonLoadBalanceClient,它們之間的關(guān)系如下圖所示。

LoadBalancerClient的父接口和實(shí)現(xiàn)類

LoadBalancerClient的父接口和實(shí)現(xiàn)類

為了大家更好地理解圖3-8所示接口及其實(shí)現(xiàn)類的實(shí)現(xiàn)細(xì)節(jié),我們先查看LoadBalancerClient的部分源碼,具體如下:

public interface LoadBalancerClient extends ServiceInstanceChooser {
     <T> T execute(String serviceId, LoadBalancerRequest<T> request) 
                      throws IOException;
     <T> T execute(String serviceId, ServiceInstance serviceInstance, 
                      LoadBalancerRequest<T> request) throws IOException;
     URI reconstructURI(ServiceInstance instance, URI original);
}

上述源碼中,LoadBalancerClient提供的兩個(gè)execute()方法用于執(zhí)行請(qǐng)求, reconstructURI()方法用于重構(gòu)URL。

繼續(xù)查看LoadBalancerClient繼承的ServiceInstanceChooser接口源碼,具體如下:

public interface ServiceInstanceChooser {
            ServiceInstance choose(String serviceId);
}

上述源碼中,ServiceInstanceChooser接口定義一個(gè)choose()方法,該方法用于根據(jù)serviceId選擇一個(gè)服務(wù)實(shí)例,即通過服務(wù)名選擇服務(wù)實(shí)例。

RibbonLoadBalanceClient是LoadBalancerClient的實(shí)現(xiàn)類,它用來執(zhí)行最終的負(fù)載均衡請(qǐng)求。其中,RibbonLoadBalanceClient的一個(gè)choose()方法用于選擇具體的服務(wù)實(shí)例,其內(nèi)部是通過getServer()方法交給ILoadBalancer完成的。

ILoadBalancer是一個(gè)接口,該接口定義了一系列實(shí)現(xiàn)負(fù)載均衡的方法。ILoadBalancer接口的實(shí)現(xiàn)類結(jié)果如下圖所示。

ILoadBalancer接口實(shí)現(xiàn)類結(jié)構(gòu)

ILoadBalancer接口實(shí)現(xiàn)類結(jié)構(gòu)

查看BaseLoadBalancer和DynamicServerListLoadBalancer源碼,默認(rèn)情況下實(shí)現(xiàn)了以下配置:

(1)IClientConfig clientConfig:用于配置負(fù)載均衡客戶端,默認(rèn)實(shí)現(xiàn)類是DefaultClientConfigImpl。

(2)IRule rule:用于配置負(fù)載均衡的策略,默認(rèn)使用的是RoundRobinRule策略,也就是輪詢策略。

(3)IPing ping:用于檢查當(dāng)前服務(wù)是否有響應(yīng),從而判斷當(dāng)前服務(wù)是否可用,默認(rèn)實(shí)現(xiàn)類是DummyPing,該實(shí)現(xiàn)類的isAlive()方法返回值是true,默認(rèn)所有服務(wù)實(shí)例都是可用的。

(4)ServerList serverList: 用于獲取所有Server注冊(cè)列表信息。通過跟蹤源碼會(huì)發(fā)現(xiàn),ServerList的實(shí)現(xiàn)類是DiscoveryEnabledNIWSServerList,該類定義的obtainServersViaDiscovery()方法是根據(jù)eurekaClientProvider.get()方法獲取EurekaClient,再根據(jù)EurekaClient獲取服務(wù)注冊(cè)列表信息。EurekaClient的實(shí)現(xiàn)類是DiscoveryClient,DiscoveryClient具有服務(wù)注冊(cè)、獲取服務(wù)注冊(cè)列表等功能。

(5)ServerListFilter filter:定義了根據(jù)配置過濾或者動(dòng)態(tài)獲取符合條件的服務(wù)列表,默認(rèn)實(shí)現(xiàn)類是ZonePreferenceServerListFilter,該策略能夠優(yōu)先過濾出與請(qǐng)求調(diào)用方處于同區(qū)域的服務(wù)實(shí)例。

綜上所述,使用RibbonLoadBalanceClient實(shí)現(xiàn)負(fù)載均衡時(shí),會(huì)從EurekaClient獲取服務(wù)列表信息,然后根據(jù)IPing判斷服務(wù)是否可用。如果服務(wù)可用,則會(huì)根據(jù)IRule選擇負(fù)載均衡策略,否則會(huì)重新獲取服務(wù)清單。

了解了LoadBalancerClient負(fù)載均衡功能后,那么RestTemplate添加@LoadBalanced注解后,為什么會(huì)被攔截呢?這是因?yàn)長oadBalancerAutoConfiguration類維護(hù)了一個(gè)被@LoadBalanced修飾的RestTemplate列表,在初始化過程中,通過調(diào)用customizer.customize(restTemplate)方法為RestTemplate添加了LoadBalancerInterceptor攔截器,該攔截器中的方法將遠(yuǎn)程服務(wù)調(diào)用的方法交給了LoadBalancerClient去處理,從而達(dá)到了負(fù)載均衡的目的。



猜你喜歡

Ribbon是什么?Ribbon詳解

Java高級(jí)軟件工程師課程

0 分享到:
和我們?cè)诰€交談!