代码里面一共有两个配置
一个是spring-cloud-common里面的org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
;另外一个是 spring-cloud-loadbalancer里面的org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration
。
spring-cloud-common正常是做规范用的,看package名称也能看出来,是配置客户端的,该类配置如下的bean:LoadBalancerRequestFactory
,该bean用于创建请求,构造函数包含LoadBalancerClient
,默认为BlockingLoadBalancerClient
。另外,注册了拦截器,并获取到RestTemplate
public class LoadBalancerAutoConfiguration {
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
/**
* 获取@LoadBalanced注解的RestTemplate
*/
@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)
@Conditional(RetryMissingOrDisabledCondition.class)
static class LoadBalancerInterceptorConfig {
@Bean
public LoadBalancerInterceptor loadBalancerInterceptor(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);
};
}
}
该配置类注册了LoadBalancerZoneConfig
和LoadBalancerClientFactory
,后者继承了ReactiveLoadBalancer.Factory<ServiceInstance>
。同时在@LoadBalancerClients
中引入了LoadBalancerClientConfigurationRegistrar
用于加载配置
该配置类用于注册LoadBalancerClient
@Bean
@ConditionalOnBean(LoadBalancerClientFactory.class)
@ConditionalOnMissingBean
public LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
return new BlockingLoadBalancerClient(loadBalancerClientFactory);
}
改配置有几个条件,@ConditionalOnClass(WebClient.class)
,@ConditionalOnBean(ReactiveLoadBalancer.Factory.class
,主要用于注册 ReactorLoadBalancerExchangeFilterFunction
用于注册LoadBalancerWebClientBuilderBeanPostProcessor
,DeferringLoadBalancerExchangeFilterFunction
loadbalancer客户端配置,配置了默认的负载规则,默认为轮训,还支持随机的
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RoundRobinLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
若引入了nacos,则nacos会默认调整为nacos的配置
NacosLoadBalancerClientConfiguration
@Bean
@ConditionalOnMissingBean
public ReactorLoadBalancer<ServiceInstance> nacosLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory,
NacosDiscoveryProperties nacosDiscoveryProperties) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new NacosLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name,
ServiceInstanceListSupplier.class),
name, nacosDiscoveryProperties);
}
nacos默认的机制为权重
ServiceInstance instance = NacosBalancer.getHostByRandomWeight3(instancesToChoose);
首先获取到添加注解的RestTemplate,然后通过拦截器LoadBalancerInterceptor
,进行请求拦截,并根据负责策略获取到最终的访问信息。
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
private LoadBalancerRequestFactory requestFactory;
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
this.loadBalancer = loadBalancer;
this.requestFactory = requestFactory;
}
public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
// for backwards compatibility
this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
}
/// 拦截
@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, this.requestFactory.createRequest(request, body, execution));
}
}
增加了注解的resttemplate默认只能请求微服务的,此时想要支持IP+端口方式的,可以在LoadBalancerInterceptor
前增加拦截器,可参考:Spring Cloud RestTemplate @LoadBalanced 支持ip、域名、服务名 调用,注意修改优先级即可
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。