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

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

Ribbon工作原理詳細介紹

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

好口碑IT培訓

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

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

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

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

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

為了大家更好地理解圖3-8所示接口及其實現(xiàn)類的實現(xiàn)細節(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提供的兩個execute()方法用于執(zhí)行請求, reconstructURI()方法用于重構(gòu)URL。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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



猜你喜歡

Ribbon是什么?Ribbon詳解

Java高級軟件工程師課程

0 分享到:
和我們在線交談!