服务发现、负载均衡和断路器等模式适用于全部Spring Cloud客户端均可以使用的通用抽象层,独立于实现(例如,使用Eureka或Consul发现)。html
Spring Cloud Commons提供@EnableDiscoveryClient
注解,这将使用META-INF/spring.factories
查找DiscoveryClient
接口的实现。Discovery Client的实现将配置类添加到org.springframework.cloud.client.discovery.EnableDiscoveryClient
键下的spring.factories
,DiscoveryClient
实现的示例包括Spring Cloud Netflix Eureka,Spring Cloud Consul Discovery和Spring Cloud Zookeeper Discovery。java
默认状况下,DiscoveryClient
的实现会使用远程发现服务器自动注册本地Spring Boot服务器,经过在@EnableDiscoveryClient
中设置autoRegister=false
能够禁用此行为。git
@EnableDiscoveryClient
已再也不须要,你能够在类路径上放置DiscoveryClient
实现,以使Spring Boot应用程序向服务发现服务器注册。
Commons建立了一个Spring Boot HealthIndicator
,DiscoveryClient
实现能够经过实现DiscoveryHealthIndicator
来参与,要禁用混合HealthIndicator
,请设置spring.cloud.discovery.client.composite-indicator.enabled=false
。基于DiscoveryClient
的通用HealthIndicator
是自动配置的(DiscoveryClientHealthIndicator
)。要禁用它,请设置spring.cloud.discovery.client.health-indicator.enabled=false
,要禁用DiscoveryClientHealthIndicator
的description
字段,请设置spring.cloud.discovery.client.health-indicator.include-description=false
,不然,它可能会像卷起的HealthIndicator
的description
同样冒出来。github
DiscoveryClient
接口扩展了Ordered
,这在使用多个发现客户端时颇有用,由于它容许你定义返回的发现客户端的顺序,相似于你能够如何排序Spring应用程序加载的bean。默认状况下,任何DiscoveryClient
的顺序都设置为0
,若是要为自定义DiscoveryClient
实现设置不一样的顺序,只需重写getOrder()
方法,以便它返回适合你的设置的值。除此以外,你还可使用属性来设置Spring Cloud提供的DiscoveryClient
实现的顺序,其中包括ConsulDiscoveryClient
,EurekaDiscoveryClient
和ZookeeperDiscoveryClient
,为此,你只需将spring.cloud.{clientIdentifier}.discovery.order
(或Eureka的eureka.client.order
)属性设置为所需的值。web
Commons如今提供一个ServiceRegistry
接口,提供register(Registration)
和deregister(Registration)
等方法,让你提供自定义注册服务,Registration
是一个标记接口。正则表达式
如下示例显示ServiceRegistry
的使用:spring
@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
实现都有本身的Registry
实现。docker
ZookeeperRegistration
与ZookeeperServiceRegistry
一块儿使用EurekaRegistration
与EurekaServiceRegistry
一块儿使用ConsulRegistration
与ConsulServiceRegistry
一块儿使用若是你使用的是ServiceRegistry
接口,则须要为正在使用的ServiceRegistry
实现传递正确的Registry
实现。apache
默认状况下,ServiceRegistry
实现会自动注册正在运行的服务,要禁用该行为,你能够设置: @EnableDiscoveryClient(autoRegister=false)
永久禁用自动注册, spring.cloud.service-registry.auto-registration.enabled=false
经过配置禁用行为。bootstrap
当服务自动注册时,将触发两个事件,第一个事件名为InstancePreRegisteredEvent
,在注册服务以前触发,第二个事件名为InstanceRegisteredEvent
,在注册服务后触发,你能够注册一个ApplicationListener
来监听并响应这些事件。
若是spring.cloud.service-registry.auto-registration.enabled
设置为false
,则不会触发这些事件。
Spring Cloud Commons提供/service-registry
执行器端点,此端点依赖于Spring Application Context中的Registration
bean,使用GET调用/service-registry
返回Registration
的状态,将POST用于具备JSON体的同一端点会将当前Registration
的状态更改成新值,JSON体必须包含具备首选值的status
字段。在更新状态和为状态返回的值时,请参阅用于容许值的ServiceRegistry
实现的文档,例如,Eureka支持的状态是UP
、DOWN
、OUT_OF_SERVICE
和UNKNOWN
。
RestTemplate
能够自动配置为使用ribbon,要建立负载均衡的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; } }
再也不经过自动配置建立
RestTemplate
bean,单个应用程序必须建立它。
URI须要使用虚拟主机名(即服务名称,而不是主机名),Ribbon客户端用于建立完整的物理地址,有关如何设置RestTemplate
的详细信息,请参见RibbonAutoConfiguration
。
WebClient
能够自动配置为使用LoadBalancerClient
,要建立负载均衡的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须要使用虚拟主机名(即服务名称,而不是主机名),Ribbon客户端用于建立完整的物理地址。
能够将负载均衡的RestTemplate
配置为重试失败的请求,默认状况下,禁用此逻辑,你能够经过将Spring Retry添加到应用程序的类路径来启用它。负载均衡的RestTemplate
支持与重试失败的请求相关的一些Ribbon配置值,你可使用client.ribbon.MaxAutoRetries
、client.ribbon.MaxAutoRetriesNextServer
和client.ribbon.OkToRetryOnAllOperations
属性,若是要在类路径上使用Spring Retry禁用重试逻辑,能够设置spring.cloud.loadbalancer.retry.enabled=false
,有关这些属性的说明,请参阅Ribbon文档。
若是要在重试中实现BackOffPolicy
,则须要建立LoadBalancedRetryFactory
类型的bean并覆盖createBackOffPolicy
方法:
@Configuration public class MyConfiguration { @Bean LoadBalancedRetryFactory retryFactory() { return new LoadBalancedRetryFactory() { @Override public BackOffPolicy createBackOffPolicy(String service) { return new ExponentialBackOffPolicy(); } }; } }
前面示例中的
client
应替换为你的Ribbon客户端的名称。
若是要将一个或多个RetryListener
实现添加到重试功能中,你须要建立一个类型为LoadBalancedRetryListenerFactory
的bean并返回你要用于给定服务的RetryListener
数组,如如下示例所示:
@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... } }}; } }; } }
若是你想要一个非负载均衡的RestTemplate
,请建立一个RestTemplate
bean并将其注入,要访问负载均衡的RestTemplate
,请在建立@Bean
时使用@LoadBalanced
限定符,如如下示例所示:
@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); } }
请注意在前面示例中的普通RestTemplate
声明中使用@Primary
注解来消除无条件的@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
。
能够将WebClient
配置为使用LoadBalancerClient
,若是spring-webflux
位于类路径上,则自动配置LoadBalancerExchangeFilterFunction
,如下示例显示如何配置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须要使用虚拟主机名(即服务名称,而不是主机名),LoadBalancerClient
用于建立完整的物理地址。
有时,忽略某些命名的网络接口以便从Service Discovery注册中排除它们(例如,在Docker容器中运行时)是有用的,能够设置正则表达式列表以使所需的网络接口被忽略,如下配置忽略docker0
接口和以veth
开头的全部接口:
application.yml
spring: cloud: inetutils: ignoredInterfaces: - docker0 - veth.*
你还可使用正则表达式列表强制仅使用指定的网络地址,如如下示例所示:
bootstrap.yml
spring: cloud: inetutils: preferredNetworks: - 192.168 - 10.0
你还能够强制仅使用站点本地地址,如如下示例所示:
application.yml
spring: cloud: inetutils: useOnlySiteLocalInterfaces: true
有关构成站点本地地址的更多详细信息,请参阅Inet4Address.html.isSiteLocalAddress()。
Spring Cloud Commons提供用于建立Apache HTTP客户端(ApacheHttpClientFactory
)和OK HTTP客户端(OkHttpClientFactory
)的bean,仅当OK HTTP jar位于类路径上时,才会建立OkHttpClientFactory
bean。此外,Spring Cloud Commons提供了建立用于两个客户端使用的链接管理器的bean:Apache HTTP客户端的ApacheHttpClientConnectionManagerFactory
和OK HTTP客户端的OkHttpClientConnectionPoolFactory
。若是要自定义在下游项目中建立HTTP客户端的方式,能够提供本身的这些bean实现,此外,若是你提供类型为HttpClientBuilder
或OkHttpClient.Builder
的bean,则默认工厂使用这些构建器做为返回到下游项目的构建器的基础,你还能够经过将spring.cloud.httpclientfactories.apache.enabled
或spring.cloud.httpclientfactories.ok.enabled
设置为false
来禁用这些bean的建立。
Spring Cloud Commons提供/features
执行器端点,此端点返回类路径上可用的特性以及它们是否已启用,返回的信息包括特性类型、名称、版本和供应商。
有两种类型的'特性':抽象和命名。
抽象特性是定义接口或抽象类并建立实现(如DiscoveryClient
、LoadBalancerClient
或LockService
)的特性,抽象类或接口用于在上下文中查找该类型的bean,显示的版本是bean.getClass().getPackage().getImplementationVersion()
。
命名特性是没有他们实现的特定类的特性,例如“断路器”,“API网关”,“Spring Cloud Bus”等,这些特性须要名称和bean类型。
任何模块均可以声明任意数量的HasFeature
bean,如如下示例所示:
@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(); }
这些bean中的每个都应该放在一个受到适当保护的@Configuration
中。
因为某些用户在设置Spring Cloud应用程序时遇到问题,所以决定添加兼容性验证机制,若是你当前的设置与Spring Cloud要求不兼容,而且报告显示出现了什么问题,它将会中断。
目前咱们验证哪一个版本的Spring Boot被添加到你的类路径中。
报告示例
*************************** APPLICATION FAILED TO START *************************** Description: Your project setup is incompatible with our requirements due to following reasons: - Spring Boot [2.1.0.RELEASE] is not compatible with this Spring Cloud release train Action: Consider applying the following actions: - Change Spring Boot version to one of the following versions [1.2.x, 1.3.x] . You can find the latest Spring Boot versions here [https://spring.io/projects/spring-boot#learn]. If you want to learn more about the Spring Cloud Release train compatibility, you can visit this page [https://spring.io/projects/spring-cloud#overview] and check the [Release Trains] section.
要禁用此功能,请将spring.cloud.compatibility-verifier.enabled
设置为false
,若是要覆盖兼容的Spring Boot版本,只需使用逗号分隔的兼容Spring Boot版本列表设置spring.cloud.compatibility-verifier.compatible-boot-versions
属性。