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

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

Ribbon工作原理詳細介紹

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

好口碑IT培訓

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

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

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

LoadBalancerClient的父接口和實現類

LoadBalancerClient的父接口和實現類

為了大家更好地理解圖3-8所示接口及其實現類的實現細節(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()方法用于重構URL。

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

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

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

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

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

ILoadBalancer接口實現類結構

ILoadBalancer接口實現類結構

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

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

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

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

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

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

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

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



猜你喜歡

Ribbon是什么?Ribbon詳解

Java高級軟件工程師課程

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