Spring Cloud Ribbon的原理
點擊上方藍色字體,選擇“標星公眾號”
優(yōu)質文章,第一時間送達
? 作者?|? 郭慕榮
來源 |? urlify.cn/fANvIr
直接開擼代碼,通過代碼來看Ribbon是如何實現(xiàn)的。

1:RibbonAutoConfiguration配置生成RibbonLoadBalancerClient實例。
代碼位置:org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
@Configuration
@Conditional({RibbonAutoConfiguration.RibbonClassesConditions.class})
@RibbonClients
@AutoConfigureAfter(
????name?=?{"org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration"}
)
@AutoConfigureBefore({LoadBalancerAutoConfiguration.class,?AsyncLoadBalancerAutoConfiguration.class})
@EnableConfigurationProperties({RibbonEagerLoadProperties.class,?ServerIntrospectorProperties.class})
public?class?RibbonAutoConfiguration?{
????@Autowired(
????????required?=?false
????)
????private?List?configurations?=?new?ArrayList();
????@Autowired
????private?RibbonEagerLoadProperties?ribbonEagerLoadProperties;
????//...略
????@Bean
????@ConditionalOnMissingBean({LoadBalancerClient.class})
????public?LoadBalancerClient?loadBalancerClient()?{
????????return?new?RibbonLoadBalancerClient(this.springClientFactory());
????}
????//?....略
}
先看配置條件項,RibbonAutoConfiguration配置必須在LoadBalancerAutoConfiguration配置前執(zhí)行,因為在LoadBalancerAutoConfiguration配置中會使用RibbonLoadBalancerClient實例。
RibbonLoadBalancerClient繼承自LoadBalancerClient接口,是負載均衡客戶端,也是負載均衡策略的調用方。
2.LoadBalancerInterceptorConfig配置生成:
1).負載均衡攔截器LoadBalancerInterceptor實例
包含:
? LoadBalancerClient實現(xiàn)類的RibbonLoadBalancerClient實例
? 負載均衡的請求創(chuàng)建工廠LoadBalancerRequestFactory:實例
2).RestTemplate自定義的RestTemplateCustomizer實例
代碼位置:org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
@Configuration(proxyBeanMethods?=?false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public?class?LoadBalancerAutoConfiguration?{
????@LoadBalanced
????@Autowired(required?=?false)
????private?List?restTemplates?=?Collections.emptyList();
????@Autowired(required?=?false)
????private?List?transformers?=?Collections.emptyList();
????@Bean
????public?SmartInitializingSingleton?loadBalancedRestTemplateInitializerDeprecated(
????????????final?ObjectProvider>?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?list?=?new?ArrayList<>(
????????????????????????restTemplate.getInterceptors());
????????????????list.add(loadBalancerInterceptor);
????????????????restTemplate.setInterceptors(list);
????????????};
????????}
????}
????????//?.....略
}
先看配置條件項:
要求在項目環(huán)境中必須要有RestTemplate類。
要求必須要有LoadBalancerClient接口的實現(xiàn)類的實例,也就是上一步生成的RibbonLoadBalancerClient。
3.通過上面一步創(chuàng)建的RestTemplateCustomizer配置所有RestTemplate實例,就是將負載均衡攔截器設置給RestTemplate實例。
@Configuration(proxyBeanMethods?=?false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public?class?LoadBalancerAutoConfiguration?{
????@LoadBalanced
????@Autowired(required?=?false)
????private?List?restTemplates?=?Collections.emptyList();
????@Autowired(required?=?false)
????private?List?transformers?=?Collections.emptyList();
????@Bean
????public?SmartInitializingSingleton?loadBalancedRestTemplateInitializerDeprecated(
????????????final?ObjectProvider>?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?list?=?new?ArrayList<>(
????????????????????????restTemplate.getInterceptors());
????????????????list.add(loadBalancerInterceptor);
????????????????restTemplate.setInterceptors(list);
????????????};
????????}
????}
????//?...略
}
restTemplate.setInterceptors(list)這個地方就是注入負載均衡攔截器的地方LoadBalancerInterceptor。
從這個地方實際上也可以猜出來,RestTemplate可以通過注入的攔截器來構建相應的請求實現(xiàn)負載均衡。
也能看出來可以自定義攔截器實現(xiàn)其他目的。
?
4.RibbonClientConfiguration配置生成ZoneAwareLoadBalancer實例
代碼位置:org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
@Configuration(proxyBeanMethods?=?false)
@EnableConfigurationProperties
@Import({?HttpClientConfiguration.class,?OkHttpRibbonConfiguration.class,
????????RestClientRibbonConfiguration.class,?HttpClientRibbonConfiguration.class?})
public?class?RibbonClientConfiguration?{
????//?...略
????@Bean
????@ConditionalOnMissingBean
????public?ILoadBalancer?ribbonLoadBalancer(IClientConfig?config,
????????????ServerList?serverList,?ServerListFilter?serverListFilter,
????????????IRule?rule,?IPing?ping,?ServerListUpdater?serverListUpdater)?{
????????if?(this.propertiesFactory.isSet(ILoadBalancer.class,?name))?{
????????????return?this.propertiesFactory.get(ILoadBalancer.class,?config,?name);
????????}
????????return?new?ZoneAwareLoadBalancer<>(config,?rule,?ping,?serverList,
????????????????serverListFilter,?serverListUpdater);
????}
???//?...略
}
ZoneAwareLoadBalancer繼承自ILoadBalancer接口,該接口有一個方法:
/**
?????*?Choose?a?server?from?load?balancer.
?????*
?????*?@param?key?An?object?that?the?load?balancer?may?use?to?determine?which?server?to?return.?null?if
?????*?????????the?load?balancer?does?not?use?this?parameter.
?????*?@return?server?chosen
?????*/
????public?Server?chooseServer(Object?key);
ZoneAwareLoadBalancer就是一個具體的負載均衡實現(xiàn)類,也是默認的負載均衡類,通過對chooseServer方法的實現(xiàn)選取某個服務實例。
粉絲福利:Java從入門到入土學習路線圖
??????

??長按上方微信二維碼?2 秒
感謝點贊支持下哈?
