3. Spring Cloud Commons:Common Abstractions
服务发现,负载平衡和断路器等模式适用于所有 Spring Cloud clients 可以使用的 common 抽象层,与 implementation 无关(对于 example,发现 Eureka 或 Consul)。
3.1 @EnableDiscoveryClient
Spring Cloud Commons 提供@EnableDiscoveryClient
annotation。这将使用META-INF/spring.factories
查找DiscoveryClient
接口的 implementations。 _ Discovery Client 的实现在org.springframework.cloud.client.discovery.EnableDiscoveryClient
key 下将 configuration class 添加到spring.factories
。 DiscoveryClient
__mplement 的示例包括Spring Cloud Netflix Eureka,Spring Cloud Consul Discovery和Spring Cloud Zookeeper Discovery。
默认情况下,DiscoveryClient
auto-register 本地 Spring Boot 服务器与 remote 发现服务器的实现。可以通过在@EnableDiscoveryClient
中设置autoRegister=false
来禁用此行为。
不再需要
@EnableDiscoveryClient
。您可以在 classpath 上放置DiscoveryClient
implementation,以使 Spring Boot application 向服务发现服务器注册。
3.1.1 健康指标
Commons _创建一个 Spring Boot HealthIndicator
,DiscoveryClient
__mplement 可以通过实现DiscoveryHealthIndicator
来参与。要禁用复合HealthIndicator
,请设置spring.cloud.discovery.client.composite-indicator.enabled=false
。基于DiscoveryClient
的通用HealthIndicator
是 auto-configured(DiscoveryClientHealthIndicator
)。要禁用它,请设置spring.cloud.discovery.client.health-indicator.enabled=false
。要禁用DiscoveryClientHealthIndicator
的描述字段,请设置spring.cloud.discovery.client.health-indicator.include-description=false
。否则,它可能会卷起HealthIndicator
卷起HealthIndicator
。
3.2 ServiceRegistry
Commons _now 提供ServiceRegistry
接口,提供register(Registration)
和deregister(Registration)
等方法,让您提供自定义注册服务。 Registration
是标记界面。
以下 example 显示正在使用的ServiceRegistry
:
@Configuration
@EnableDiscoveryClient(autoRegister=false)
public class MyConfiguration {
private ServiceRegistry registry;
public MyConfiguration(ServiceRegistry registry) {
this.registry = registry;
}
// called through some external process, such as an event or a custom actuator endpoint
public void register() {
Registration registration = constructRegistration();
this.registry.register(registration);
}
}
每个ServiceRegistry
implementation 都有自己的Registry
implementation。
-
ZookeeperRegistration
与ZookeeperServiceRegistry
一起使用 -
EurekaRegistration
与EurekaServiceRegistry
一起使用 -
ConsulRegistration
与ConsulServiceRegistry
一起使用
如果您使用ServiceRegistry
接口,则需要为正在使用的ServiceRegistry
implementation 传递正确的Registry
implementation。
3.2.1 ServiceRegistry Auto-Registration
默认情况下,ServiceRegistry
implementation auto-registers _运行服务。要禁用该行为,您可以设置:* @EnableDiscoveryClient(autoRegister=false)
永久禁用 auto-registration。 * spring.cloud.service-registry.auto-registration.enabled=false
通过 configuration 禁用行为。
ServiceRegistry Auto-Registration Events
服务 auto-registers 时会触发两个 event。第一个 event,名为InstancePreRegisteredEvent
,在注册服务之前被触发。第二个 event,名为InstanceRegisteredEvent
,在注册服务后触发。您可以注册ApplicationListener
(s)来收听并对这些 events 做出反应。
如果
spring.cloud.service-registry.auto-registration.enabled
设置为false
,则不会触发这些 events。
3.2.2 Service Registry Actuator 端点
Spring Cloud Commons 提供/service-registry
actuator 端点。此端点依赖于 Spring Application Context 中的Registration
bean。使用 GET 调用/service-registry
将返回Registration
的状态。将 POST 用于具有 JSON 主体的同一端点会将当前Registration
的状态更改为新的 value。 JSON 主体必须包含status
字段和首选 value。更新状态和为状态返回的值时,请参阅用于允许值的ServiceRegistry
implementation 的文档。例如,Eureka 支持的状态是UP
,DOWN
,OUT_OF_SERVICE
和UNKNOWN
。
3.3 Spring RestTemplate 作为负载均衡器 Client
RestTemplate
可以自动配置为使用 ribbon。要创建 load-balanced RestTemplate
,请创建RestTemplate
@Bean
并使用@LoadBalanced
限定符,如下面的示例所示:
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private RestTemplate restTemplate;
public String doOtherStuff() {
String results = restTemplate.getForObject("http://stores/stores", String.class);
return results;
}
}
不再通过 auto-configuration 创建
RestTemplate
bean。单个 applications 必须创建它。
URI 需要使用虚拟 host name(即服务 name,而不是 host name)。 Ribbon client 用于创建完整的物理地址。有关如何设置RestTemplate
的详细信息,请参阅RibbonAutoConfiguration。
3.4 Spring WebClient 作为负载均衡器 Client
WebClient
可以自动配置为使用LoadBalancerClient
。要创建 load-balanced WebClient
,请创建WebClient.Builder
@Bean
并使用@LoadBalanced
限定符,如下面的示例所示:
@Configuration
public class MyConfiguration {
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
public class MyClass {
@Autowired
private WebClient.Builder webClientBuilder;
public Mono<String> doOtherStuff() {
return webClientBuilder.build().get().uri("http://stores/stores")
.retrieve().bodyToMono(String.class);
}
}
URI 需要使用虚拟 host name(即服务 name,而不是 host name)。 Ribbon client 用于创建完整的物理地址。
3.4.1 重试失败的请求
可以将 load-balanced RestTemplate
配置为重试失败的请求。默认情况下,禁用此逻辑。您可以通过将Spring 重试添加到 application 的 classpath 来启用它。 load-balanced RestTemplate
尊重与重试失败请求相关的一些 Ribbon configuration 值。您可以使用client.ribbon.MaxAutoRetries
,client.ribbon.MaxAutoRetriesNextServer
和client.ribbon.OkToRetryOnAllOperations
properties。如果要在 classpath 上使用 Spring Retry 禁用重试逻辑,可以设置spring.cloud.loadbalancer.retry.enabled=false
。有关这些 properties 的说明,请参阅Ribbon 文档。
如果要在重试中实现BackOffPolicy
,则需要创建类型的 bean 并覆盖createBackOffPolicy
方法:
@Configuration
public class MyConfiguration {
@Bean
LoadBalancedRetryFactory retryFactory() {
return new LoadBalancedRetryFactory() {
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return new ExponentialBackOffPolicy();
}
};
}
}
前面示例中的
client
应替换为 Ribbon client 的 name。
如果要在重试功能中添加一个或多个RetryListener
__mplement,则需要创建类型的 bean 并_返回要用于给定服务的RetryListener
array,如下面的示例所示:
@Configuration
public class MyConfiguration {
@Bean
LoadBalancedRetryListenerFactory retryListenerFactory() {
return new LoadBalancedRetryListenerFactory() {
@Override
public RetryListener[] createRetryListeners(String service) {
return new RetryListener[]{new RetryListener() {
@Override
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
//TODO Do you business...
return true;
}
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
//TODO Do you business...
}
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
//TODO Do you business...
}
}};
}
};
}
}
3.5 多个 RestTemplate objects
如果你想要一个不是 load-balanced 的RestTemplate
,创建一个RestTemplate
bean 并 inject 它。要访问 load-balanced RestTemplate
,请在创建@Bean
时使用@LoadBalanced
限定符,如下面的 example 所示:\
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate loadBalanced() {
return new RestTemplate();
}
@Primary
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private RestTemplate restTemplate;
@Autowired
@LoadBalanced
private RestTemplate loadBalanced;
public String doOtherStuff() {
return loadBalanced.getForObject("http://stores/stores", String.class);
}
public String doStuff() {
return restTemplate.getForObject("http://example.com", String.class);
}
}
注意在前面的 example 中的 plain
RestTemplate
声明上使用@Primary
annotation 来消除不合格的@Autowired
注入的歧义。
如果您看到
java.lang.IllegalArgumentException: Can not set org.springframework.web.client.RestTemplate field com.my.app.Foo.restTemplate to com.sun.proxy.$Proxy89
等错误,请尝试注入RestOperations
或设置spring.aop.proxyTargetClass=true
。
3.6 Spring WebFlux WebClient 作为负载均衡器 Client
WebClient
可以配置为使用LoadBalancerClient
。如果spring-webflux
在 classpath 上,LoadBalancerExchangeFilterFunction
是 auto-configured。以下 example 显示了如何配置WebClient
以使用负载均衡器:
public class MyClass {
@Autowired
private LoadBalancerExchangeFilterFunction lbFunction;
public Mono<String> doOtherStuff() {
return WebClient.builder().baseUrl("http://stores")
.filter(lbFunction)
.build()
.get()
.uri("/stores")
.retrieve()
.bodyToMono(String.class);
}
}
URI 需要使用虚拟 host name(即服务 name,而不是 host name)。 LoadBalancerClient
用于创建完整的物理地址。
3.7 忽略网络接口
有时,忽略某些命名的网络接口以便可以从 Service Discovery 注册中排除它们(例如,在 Docker 容器中运行时)。可以设置正则表达式列表以使所需的网络接口被忽略。以下 configuration 忽略docker0
接口和所有以veth
开头的接口:
application.yml.
spring:
cloud:
inetutils:
ignoredInterfaces:
- docker0
- veth.*
您还可以使用正则表达式列表强制仅使用指定的网络地址,如下面的示例所示:
bootstrap.yml.
spring:
cloud:
inetutils:
preferredNetworks:
- 192.168
- 10.0
您还可以强制仅使用 site-local 地址,如下例所示:.application.yml
spring:
cloud:
inetutils:
useOnlySiteLocalInterfaces: true
有关 site-local 地址构成的更多详细信息,请参阅Inet4Address.html.isSiteLocalAddress()。
3.8 HTTP Client Factories
Spring Cloud Commons _provides beans for creating Apache HTTP clients(ApacheHttpClientFactory
)和 OK HTTP clients(OkHttpClientFactory
)。只有在 classpath 上有 OK HTTP jar 时才会创建OkHttpClientFactory
bean。另外,Spring Cloud Commons _provides beans 用于创建两个 clients 使用的连接_manage:ApacheHttpClientConnectionManagerFactory
用于 Apache HTTP client,OkHttpClientConnectionPoolFactory
用于 OK HTTP client。如果您想自定义在下游项目中创建 HTTP clients 的方式,您可以提供自己的_bemplementation beans。此外,如果提供HttpClientBuilder
或OkHttpClient.Builder
类型的 bean,则默认工厂将使用这些构建器作为返回到下游项目的构建器的基础。您还可以通过将spring.cloud.httpclientfactories.apache.enabled
或spring.cloud.httpclientfactories.ok.enabled
设置为false
来禁用这些 beans 的创建。
3.9 已启用 Features
Spring Cloud Commons 提供/features
actuator 端点。此端点返回 classpath 上可用的 features 以及它们是否已启用。返回的信息包括 feature 类型,name,version 和 vendor。
3.9.1 特征类型
有两种类型的'features':抽象和命名。
抽象 features 是 features,其中定义了接口或抽象 class,并且创建了 implementation,例如DiscoveryClient
,LoadBalancerClient
或LockService
。 abstract class 或 interface 用于在 context 中查找该类型的 bean。显示的 version 是bean.getClass().getPackage().getImplementationVersion()
。
命名 features 是 features 没有他们实现的特定 class,例如“Circuit Breaker”,“API Gateway”,“ Spring Cloud Bus”等。这些 features 需要 name 和 bean 类型。
3.9.2 声明 features
任何模块都可以声明任意数量的HasFeature
beans,如以下示例所示:
@Bean
public HasFeatures commonsFeatures() {
return HasFeatures.abstractFeatures(DiscoveryClient.class, LoadBalancerClient.class);
}
@Bean
public HasFeatures consulFeatures() {
return HasFeatures.namedFeatures(
new NamedFeature("Spring Cloud Bus", ConsulBusAutoConfiguration.class),
new NamedFeature("Circuit Breaker", HystrixCommandAspect.class));
}
@Bean
HasFeatures localFeatures() {
return HasFeatures.builder()
.abstractFeature(Foo.class)
.namedFeature(new NamedFeature("Bar Feature", Bar.class))
.abstractFeature(Baz.class)
.build();
}
这些 beans 中的每一个都应该进行适当的保护@Configuration
。