springCloud的LoadBalance源码分析
欢迎查看Eetal的第二十篇博客–SpringCloud的LoadBalance源码分析
相关核心类
LoadBalanced
LoadBalancerClient
LoadBalancerAutoConfiguration
LoadBalancerInterceptor
RibbonAutoConfiguration
RibbonClassesConditions
AllNestedConditions
AbstractNestedCondition
AbstractNestedCondition.MemberMatchOutcomes
AbstractNestedCondition.MemberConditions
SpringBootCondition
ConditionOutcome
LoadBalanced注解与功能
通过在创建的RestTemplate上加入LoadBalanced注解,则该RestTemplate会自动成为负载均衡的RestTeplate,请求的url的hostname会作为服务名称去解析
用法如下
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public String requestTest(){
String url = "http://8781-eurekaClient/getClient2Info";
return restTemplate.getForObject(url, String.class);
}
等价于以下写法
@Autowired
RestTemplate restTemplate;
@Autowired
private LoadBalancerClient client;
@RequestMapping("/getProviderInfo")
public String getProviderInfo() {
ServiceInstance instance = client.choose("8780-eurekaClient");
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/getInfo";
return restTemplate.getForObject(url, String.class);
}
源码分析
1.LoadBalanced注解
@Target({
ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}
这里注意,该注解被标记了@Qualifier注解,后续使用@Autowired注解注入时,如果注解的属性也被LoadBalanced注解,则只装载一样被LoadBalanced注解的符合autowired的对象
2.LoadBalnceAutoConfigure
@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
@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
@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 LoadBalanc