SpringCloud之Consul服务发现源码分析

1、RibbonConsulAutoConfiguration

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnConsulEnabled
@ConditionalOnBean(SpringClientFactory.class)
@ConditionalOnProperty(value = "spring.cloud.consul.ribbon.enabled",
		matchIfMissing = true)
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = ConsulRibbonClientConfiguration.class)
public class RibbonConsulAutoConfiguration {
    
    

}

2、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 {
    
    

	@Bean
	public SpringClientFactory springClientFactory() {
    
    
		SpringClientFactory factory = new SpringClientFactory();
		factory.setConfigurations(this.configurations);
		return factory;
	}

	@Bean
	@ConditionalOnMissingBean(LoadBalancerClient.class)
	public LoadBalancerClient loadBalancerClient() {
    
    
		return new RibbonLoadBalancerClient(springClientFactory());
	}

	@Bean
	@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
	@ConditionalOnMissingBean
	public LoadBalancedRetryFactory loadBalancedRetryPolicyFactory(
			final SpringClientFactory clientFactory) {
    
    
		return new RibbonLoadBalancedRetryFactory(clientFactory);
	}

	@Bean
	@ConditionalOnMissingBean
	public PropertiesFactory propertiesFactory() {
    
    
		return new PropertiesFactory();
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(HttpRequest.class)
	@ConditionalOnRibbonRestClient
	protected static class RibbonClientHttpRequestFactoryConfiguration {
    
    

		@Autowired
		private SpringClientFactory springClientFactory;

		@Bean
		public RestTemplateCustomizer restTemplateCustomizer(
				final RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory) {
    
    
			return restTemplate -> restTemplate
					.setRequestFactory(ribbonClientHttpRequestFactory);
		}

		@Bean
		public RibbonClientHttpRequestFactory ribbonClientHttpRequestFactory() {
    
    
			return new RibbonClientHttpRequestFactory(this.springClientFactory);
		}

	}
}

目的是初始化LoadBalancerClient

3、LoadBalancerAutoConfiguration

@Configuration(proxyBeanMethods = false)
@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(// 示例1
			ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
    
    //入参需要实例化RestTemplateCustomizer
		return () -> restTemplateCustomizers.ifAvailable(customizers -> {
    
    //调用SmartInitializingSingleton默认方法
			for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
    
    
				for (RestTemplateCustomizer customizer : customizers) {
    
    
					customizer.customize(restTemplate);// 对接口RestTemplateCustomizer抽象方法的调用
				}
			}
		});
	}

	@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(//这种方式是实例化RestTemplateCustomizer实例   示例2
				final LoadBalancerInterceptor loadBalancerInterceptor) {
    
    
			return restTemplate -> {
    
    // 对接口RestTemplateCustomizer中抽象方法的实现
				List<ClientHttpRequestInterceptor> list = new ArrayList<>(
						restTemplate.getInterceptors());
				list.add(loadBalancerInterceptor);
				restTemplate.setInterceptors(list);
			};
		}
	}
}
  1. 该配置类的作用是对RestTemplate设置拦截器LoadBalancerInterceptor
  2. SmartInitializingSingleton类抽象方法调用时机为:DefaultListableBeanFactory#preInstantiateSingletons。【Trigger post-initialization callback for all applicable beans…】
  3. 示例1、示例2都是通过匿名内部类方式对bean进行实例化,同时通过lamada表达式实现接口的抽象方法。

4、服务发现

通过 RestTemplate#doExecute【ClientHttpRequest#execute】 中拦截器实现注册中心客户端的负载均衡。

4.1、InterceptingClientHttpRequest

class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest {
    
    

	private final List<ClientHttpRequestInterceptor> interceptors;
	
	private class InterceptingRequestExecution implements ClientHttpRequestExecution {
    
    
	
			private final Iterator<ClientHttpRequestInterceptor> iterator;

			public InterceptingRequestExecution() {
    
    
				this.iterator = interceptors.iterator();
			}
			public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
    
    
					if (this.iterator.hasNext()) {
    
    
						ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
						return nextInterceptor.intercept(request, body, this);
					}else{
    
     ... }
			  }
	}
}

4.2、LoadBalancerInterceptor

public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
		final ClientHttpRequestExecution execution) throws IOException {
    
    
	final URI originalUri = request.getURI();
	String serviceName = originalUri.getHost();
	return this.loadBalancer.execute(serviceName,
			this.requestFactory.createRequest(request, body, execution));
}

4.3、RibbonLoadBalancerClient

public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint){
    
    
	获取ILoadBalancer接口的某种负载均衡策略
	ILoadBalancer loadBalancer = getLoadBalancer(serviceId);//servicedId是从restTemplate客户端的URL中获取得到
	Server server = getServer(loadBalancer, hint);//利用默认的负载策略ZoneAwareLoadBalancer获取目标服务的IP、端口号等信息
	RibbonServer ribbonServer = new RibbonServer(serviceId, server,
			isSecure(server, serviceId),
			serverIntrospector(serviceId).getMetadata(server));
	return execute(serviceId, ribbonServer, request);
}

具体过程参考:服务发现

猜你喜欢

转载自blog.csdn.net/qq_36851469/article/details/127944584
今日推荐