上一篇文章《探究 Eureka 在 Spring Boot 中的配置注入与统一管理机制(中)》,我们揭示了springboot项目在启动时,最终被加载到spring容器里的eureka的相关配置类有5个。
今天我们来探讨下已经加载到Spring容器中的Eureka客户端相关的第一个自动配置类是如何进行初始化的。
DiscoveryClientOptionalArgsConfiguration
DiscoveryClientOptionalArgsConfiguration提供了几种不同类型的客户端选项参数(AbstractDiscoveryClientOptionalArgs))的实现。下面我们来看每个关键部分。
1. TlsProperties Bean创建
@Bean
@ConfigurationProperties("eureka.client.tls")
public TlsProperties tlsProperties() {
return new TlsProperties();
}
- 作用:将所有TLS(Transport Layer Security)配置集中在一个bean中,方便管理和修改,同时确保了Eureka客户端能够安全地与Eureka服务端进行通信。
2. RestTemplate客户端创建
@Bean
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
matchIfMissing = true, havingValue = "false")
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(
TlsProperties tlsProperties) throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses RestTemplate.");
RestTemplateDiscoveryClientOptionalArgs result = new RestTemplateDiscoveryClientOptionalArgs();
setupTLS(result, tlsProperties);
return result;
}
- 创建条件
- 类路径中没有com.sun.jersey.api.client.filter.ClientFilter类(即没有使用Jersey客户端)。
- 类路径中没有AbstractDiscoveryClientOptionalArgs类型的Bean。
- 配置eureka.client.webclient.enabled为false或未设置(默认值为false)
- 作用:确保了Eureka客户端能够正确地初始化一个安全的HTTP客户端(RestTemplate),并且能够与Eureka服务端进行安全的HTTP通信。
- TLS配置:确保Eureka客户端与服务端之间的通信是加密的。
3. Jersey 客户端配置
@Bean
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class,
search = SearchStrategy.CURRENT)
public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs(
TlsProperties tlsProperties) throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses Jersey");
MutableDiscoveryClientOptionalArgs result = new MutableDiscoveryClientOptionalArgs();
setupTLS(result, tlsProperties);
return result;
}
- 创建条件
- 类路径中存在com.sun.jersey.api.client.filter.ClientFilter类(即使用Jersey客户端)。
- 类路径中没有AbstractDiscoveryClientOptionalArgs类型的Bean。
- 作用:同上。
- TLS配置:同上。
这里简单补充下,Jersey 客户端与RestTemplate客户端的不同
- Jersey是基于JAX-RS(Java API for RESTful Web Services)规范,用于构建RESTful风格的Web服务, 异步的场景用的最多。
- RestTemplate是Spring框架提供的用于进行同步 HTTP 请求的工具。
后期会专门出一篇文章来比较微服务架构中,常用的的Http客户端的异同。
4. WebClientConfiguration客户端配置
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnClass(
name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
protected static class WebClientConfiguration {
@Autowired
private TlsProperties tlsProperties;
@Bean
@ConditionalOnMissingBean(
value = { AbstractDiscoveryClientOptionalArgs.class,
RestTemplateDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
public WebClientDiscoveryClientOptionalArgs webClientDiscoveryClientOptionalArgs(
ObjectProvider<WebClient.Builder> builder)
throws GeneralSecurityException, IOException {
logger.info("Eureka HTTP Client uses WebClient.");
WebClientDiscoveryClientOptionalArgs result = new WebClientDiscoveryClientOptionalArgs(
builder::getIfAvailable);
setupTLS(result, tlsProperties);
return result;
}
}
- 生效条件
- 类路径中不存在com.sun.jersey.api.client.filter.ClientFilter类(即没有使用Jersey客户端)。
- 类路径中存在org.springframework.web.reactive.function.client.WebClient类。
- 配置eureka.client.webclient.enabled为true。
- 作用:它是一个静态内部类,用于在特定条件下配置使用
WebClient
作为 Eureka 的 HTTP 客户端,并创建相关的配置对象。 - TLS配置:同上。
5.WebClient 未找到时的处理
@Configuration
@ConditionalOnMissingClass({ "com.sun.jersey.api.client.filter.ClientFilter",
"org.springframework.web.reactive.function.client.WebClient" })
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
protected static class WebClientNotFoundConfiguration {
public WebClientNotFoundConfiguration() {
throw new IllegalStateException("eureka.client.webclient.enabled is true, "
+ "but WebClient is not on the classpath. Please add "
+ "spring-boot-starter-webflux as a dependency.");
}
}
- 生效条件
- 类路径中不存在com.sun.jersey.api.client.filter.ClientFilter类(即没有使用Jersey客户端)。
- 类路径中不存在org.springframework.web.reactive.function.client.WebClient类。
- 配置eureka.client.webclient.enabled为true。
当上述条件满足时,会抛IllegalStateException异常提示用户添加spring-boot-starter-webflux依赖。
最后,我们在总结下,DiscoveryClientOptionalArgsConfiguration配置类在初始化的过程中,主要创建了TlsProperties类实例,并根据不同类型的客户端类型(WebClient,RestTemplate以及Jersey客户端)创建了相应的配置类实例,确保这些客户端能够安全地与Eureka服务端进行通信。