服務發現、負載均衡和斷路器等模式適用於全部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
屬性。