3. Spring Cloud Commons:共通的抽象
服務發現,負載平衡和斷路器等模式是所有Spring Cloud客戶端可以使用的公共抽象層,與實現無關(例如,使用Eureka或Consul進行發現)。
3.1 @EnableDiscoveryClient
Spring Cloud Commons提供了@EnableDiscoveryClient
註解。這將用META-INF/spring.factories
查找DiscoveryClient
接口的實現。Discovery Client的實現在spring.factories的
org.springframework.cloud.client.discovery.EnableDiscoveryClient key
下添加一個配置類。DiscoveryClient實現的例子
包括Spring Cloud Netflix Eureka,Spring Cloud Consul Discovery和Spring Cloud Zookeeper Discovery。
默認情況下,DiscoveryClient的實現類
使用遠程發現服務器自動註冊本地Spring Boot服務器。這種行爲可以通過在@EnableDiscoveryClient
設置autoRegister=false
被禁用。
|
3.1.1 健康指示
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
的描述字段,請設置spring.cloud.discovery.client.health-indicator.include-description=false
。否則,它會在rolled up HealthIndicator中冒出來描述。
3.1.2 給DiscoveryClient
實例排序
DiscoveryClient接口
擴展Ordered
。這在使用多個DiscoveryClient
時很有用,因爲它允許您定義返回的DiscoveryClient
的順序,類似於您可以如何排序Spring應用程序加載的bean。默認情況下,任意DiscoveryClient
設置的順序爲 0
。如果要爲自定義DiscoveryClient
實現設置不同的順序,則只需覆蓋該getOrder()
方法,以便返回適合您的設置的值。除了這個,你可以使用屬性來設置Spring Cloud提供的DiscoveryClient實現的順序,如ConsulDiscoveryClient
,EurekaDiscoveryClient
和 ZookeeperDiscoveryClient
。爲此,您只需將spring.cloud.{clientIdentifier}.discovery.order
(或爲Eureka設置eureka.client.order
)屬性設置爲所需的值即可。
3.2 ServiceRegistry
Commons現在提供了一個ServiceRegistry接口,它
提供諸如register(Registration)
和deregister(Registration)
,它允許您提供自定義註冊服務。 Registration
是一個標記接口。
以下示例顯示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
實現都有自己的Registry
實現。
ZookeeperRegistration
用於ZookeeperServiceRegistry
EurekaRegistration
用於EurekaServiceRegistry
ConsulRegistration
用於ConsulServiceRegistry
如果您正在使用ServiceRegistry
接口,則需要爲正在使用的ServiceRegistry
實現傳遞正確的Registry
實現。
3.2.1 ServiceRegistry自動註冊
默認情況下,ServiceRegistry
實現會自動註冊正在運行的服務。要禁用該行爲,您可以設置:* @EnableDiscoveryClient(autoRegister=false)
永久禁用自動註冊。* spring.cloud.service-registry.auto-registration.enabled=false
通過配置禁用行爲。
ServiceRegistry自動註冊事件
當服務自動註冊時,將觸發兩個事件。名爲InstancePreRegisteredEvent
的第一個事件 在註冊服務之前被觸發。第二個事件叫做InstanceRegisteredEvent
,在服務註冊後被觸發。您可以註冊一個 ApplicationListener
(s)來收聽並回應這些事件。
如果 |
3.2.2 服務註冊Actuator端點(Service Registry Actuator Endpoint)
Spring Cloud Commons提供/service-registry
執行器端點。此端點依賴於Registration bean,它處於
Spring Application Context中。/service-registry
使用GET 調用返回Registration
的狀態。將POST用於具有JSON主體的同一端點會將當前狀態更改Registration
爲新值。JSON主體必須包含status
具有首選值的字段。ServiceRegistry
更新狀態和爲狀態返回的值時,請參閱您用於允許值的實現的文檔。例如,Eureka支持的狀態是UP
,DOWN
,OUT_OF_SERVICE
,和UNKNOWN
。
3.3 Spring RestTemplate作爲負載均衡器客戶端
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;
}
}
警告 | |
---|---|
|
URI需要使用虛擬主機名(即服務名稱,而不是主機名)。Ribbon客戶端用於創建完整的物理地址。有關如何設置RestTemplate
的詳細信息,請參見RibbonAutoConfiguration。
3.4 Spring WebClient作爲負載均衡器客戶端
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客戶端用於創建完整的物理地址。
3.4.1重試失敗的請求
負載均衡的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...
}
}};
}
};
}
}
3.5 多個RestTemplate對象
如果你想要一個不負載平衡的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("https://example.com", String.class);
}
}
重要 | |
---|---|
請注意在前面示例中給簡單 |
如果您看到錯誤 |
3.6 Spring WebFlux WebClient作爲負載均衡器客戶端
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
用於創建一個完整的物理地址。
3.7忽略網絡接口
有時,忽略某些名稱的網絡接口以便從服務發現註冊中排除它們(例如,在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()。
3.8 HTTP客戶端工廠
Spring Cloud Commons提供了用於創建Apache HTTP客戶端(ApacheHttpClientFactory
)和OK HTTP客戶端(OkHttpClientFactory
)的bean 。僅當OK HTTP jar在classpath中OkHttpClientFactory才能被
創建。此外,Spring Cloud Commons提供了用於創建兩個客戶端使用的連接管理器的bean:
ApacheHttpClientConnectionManagerFactory 用於
Apache HTTP客戶端
OkHttpClientConnectionPoolFactory 用於
OK HTTP客戶端。
如果要自定義在下游項目中創建HTTP客戶端的方式,可以提供自己的這些bean的實現。此外,如果您提供HttpClientBuilder
或OkHttpClient.Builder
類型的Bean,默認的工廠使用這些Builder
作爲Builder
的基礎返回給下游項目。您還可以通過設置spring.cloud.httpclientfactories.apache.enabled
或spring.cloud.httpclientfactories.ok.enabled爲false,
來禁用這些bean的創建。
3.9啓用特性
Spring Cloud Commons提供/features
actuator端點。此端點返回類路徑上可用的功能以及它們是否已啓用。返回的信息包括功能類型,名稱,版本和供應商。
3.9.1特性類型
有兩種類型的'特性':抽象和命名。
抽象特性是指接口或抽象類的定義以及它們的一個實現,例如DiscoveryClient
,LoadBalancerClient
,或LockService
。抽象類或接口用於在上下文中查找該類型的bean。下面的代碼可以顯示版本。bean.getClass().getPackage().getImplementationVersion()
。
命名特性是指一些沒有特定實現類的特性,例如“斷路器”,“API網關”,“Spring Cloud Bus”等。這些功能需要一個名稱和bean類型。
3.9.2聲明特性
任何模塊都可以聲明任意數量的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
適當的保護。
3.10 Spring Cloud兼容性驗證
由於某些用戶在創建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
屬性即可。