Spring Cloud教程 第三彈 Ribbon工作原理
寫在前面的話
本文只介紹Ribbon的工作原理,關於Ribbon的其它教程請看這篇文章 Spring Cloud教程 第二彈 客戶端負載均衡Ribbon
因為Ribbon的工作原理我寫的有點細,篇幅稍大,所以單獨抽出來了,沒有將本文糅合在第二彈裡
1、揭開RestTemplate的神祕面紗
我們實際上關心的是,為什麼@LoadBalanced註解能賦予RestTemplate負載均衡的能力?
關於Ribbon的核心工作原理,請小夥伴們一定要一步一步耐心往下看。
首先,Ribbon元件在啟動時,會自動載入RibbonAutoConfiguration這個配置類,如下圖所示
可以看到,RibbonAutoConfiguration載入於EurekaClientAutoConfiguration之前,載入於LoadBalancerAutoConfiguration之後
EurekaClientAutoConfiguration不必多說,引入Eureka Client必然會載入這個類
而RibbonAutoConfiguration中宣告瞭這樣的一個Bean,如下圖所示
RibbonLoadBalancerClient主要為載入LoadBalancerAutoConfiguration服務,沒有RibbonLoadBalancerClient這個Bean,後者無法載入,具體細節看下圖。
下面主要就來看看LoadBalancerAutoConfiguration這個類做了什麼事情
首先,LoadBalancerAutoConfiguration有這樣一塊程式碼:
這塊程式碼表示的含義是:將所有用@LoadBalanced註解標識的RestTemplate型別的Bean注入到List集合中,而恰好我們的確也宣告瞭這樣的一個Bean,如下圖所示:
這不就是我們很熟悉的那塊程式碼嘛
@LoadBalanced註解與@Qualifier註解有關,關於@LoadBalanced註解的原理請看這篇文章 Ribbon中@LoadBalanced註解的原理
另外,LoadBalancerAutoConfiguration類中還有另外幾塊重要的程式碼,為了保持整潔,不重要的我就沒有貼上出來了,如下所示。
public class LoadBalancerAutoConfiguration {
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
});
}
@Bean
@ConditionalOnMissingBean
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig {
@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
}
}
1、loadBalancerRequestFactory方法用於宣告一個負載均衡請求生成工廠
2、LoadBalancerInterceptorConfig 這個內部靜態類宣告瞭兩個Bean:
2.1、ribbonInterceptor:該方法宣告瞭一個負載均衡攔截器的Bean,該方法有兩個引數loadBalancerClient、LoadBalancerRequestFactory requestFactory,這兩個引數都已經有了。而LoadBalancerInterceptor繼承自ClientHttpRequestInterceptor,表明LoadBalancerInterceptor就是spring boot的一個攔截器
2.2、restTemplateCustomizer:該方法用於宣告一個RestTemplateCustomizer型別的Bean。該bean的目的在於:將RestTemplate與LoadBalancerInterceptor繫結起來,這是RestTemplate具有負載均衡能力的關鍵
3、loadBalancedRestTemplateInitializerDeprecated方法用於觸發RestTemplateCustomizer這個Bean的執行
綜上所述,RestTemplate發出的請求最後是被LoadBalancerInterceptor這個攔截器攔截到了,下面看一下LoadBalancerInterceptor的intercept方法主要做了哪些事情:
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
}
最終的請求交由loadBalancer這個負載均衡器執行,this.loadBalancer的型別是LoadBalancerClient,而LoadBalancerClient的實現為RibbonLoadBalancerClient,LoadBalancerClient繼承自ServiceInstanceChooser介面
public interface ServiceInstanceChooser {
ServiceInstance choose(String serviceId);
}
通過this.loadBalancer.execute這行程式碼往裡面跟蹤,找到最終的執行方法如下(execute-1會呼叫execute-2):
getServer方法的實現細節:
ILoadBalancer的chooseServer方法會轉換為呼叫IRule的choose方法,這與我在前面所說的形成了前呼後應
request.apply方法的實現細節:
request物件是在LoadBalancerInterceptor的intercept方法中傳過來的,具體如下圖:
點進去看看,如下圖:
最後的execution.execute方法是執行最終的http請求的地方,至此,一次ribbon的生命週期就到此結束了。
總結
關於Ribbon的工作原理,我寫的雖然有點多,但是很詳細,耐心看完的話基本沒有啥疑問的,該懂的都會懂。當你讀懂之後,發現Ribbon似乎不再神祕了
相關文章
- Spring-Cloud之Ribbon原理剖析SpringCloud
- Spring Cloud之負載均衡元件Ribbon原理分析SpringCloud負載元件
- 深度解析Spring Cloud Ribbon的實現原始碼及原理SpringCloud原始碼
- Spring Cloud Ribbon負載均衡SpringCloud負載
- Spring Cloud應用(二)---ribbon使用SpringCloud
- Spring Cloud入門教程-Ribbon實現客戶端負載均衡SpringCloud客戶端負載
- Spring cloud(3)-負載均衡(Feign,Ribbon)SpringCloud負載
- 客服端負載均衡:Spring Cloud Ribbon負載SpringCloud
- Spring Cloud Ribbon之URL重構(三)SpringCloud
- Spring Cloud:自定義 Ribbon 負載均衡策略SpringCloud負載
- Spring Cloud Ribbon 客戶端負載均衡SpringCloud客戶端負載
- springcloud學習筆記(三)Spring Cloud RibbonSpringGCCloud筆記
- Spring Cloud Netflix—自定義Ribbon客戶端SpringCloud客戶端
- Spring Cloud教程 第九彈 微服務閘道器ZuulSpringCloud微服務Zuul
- 跟我學Spring Cloud(Finchley版)-08-Ribbon深入SpringCloud
- Spring Cloud Netflix—示例在Ribbon中禁用Eureka使用SpringCloud
- spring cloud構建網際網路分散式微服務雲平臺- Ribbon設計原理SpringCloud分散式微服務
- Spring Cloud底層原理SpringCloud
- Spring Cloud:使用Ribbon實現負載均衡詳解(上)SpringCloud負載
- Spring Cloud:使用Ribbon實現負載均衡詳解(下)SpringCloud負載
- Spring Cloud實戰系列(二) - 客戶端呼叫Rest + RibbonSpringCloud客戶端REST
- 微服務Spring Cloud17_負載均衡Ribbon6微服務SpringCloud負載
- Spring Cloud負載均衡神器——Ribbon簡介與基本使用SpringCloud負載
- Spring Cloud Netflix—客戶端負載平衡器:RibbonSpringCloud客戶端負載
- Spring Cloud基礎教程SpringCloud
- Spring Session工作原理SpringSession
- Spring Cloud Feign設計原理SpringCloud
- Spring Cloud OpenFeign的原理(六)SpringCloud
- spring cloud生態中Feign、Ribbon、loadbalancer的一些歷史SpringCloud
- Spring Cloud OpenFeign:基於Ribbon和Hystrix的宣告式服務呼叫SpringCloud
- 深度剖析Spring Cloud底層原理SpringCloud
- Spring Cloud底層原理(核心元件)SpringCloud元件
- Spring-Cloud之Feign原理剖析SpringCloud
- Spring Cloud Alibaba教程:Sentinel的使用SpringCloud
- Spring Cloud Alibba教程:Sentinel的使用SpringCloud
- Spring Cloud中Hystrix、Ribbon及Feign的熔斷關係是什麼?SpringCloud
- spring-mvc的工作原理SpringMVC
- Spring Cloud Feign設計原理(轉載)SpringCloud