Spring Cloud 參考文檔(Spring Cloud Commons:通用的抽象)

Spring Cloud Commons:通用的抽象

服務發現、負載均衡和斷路器等模式適用於全部Spring Cloud客戶端均可以使用的通用抽象層,獨立於實現(例如,使用Eureka或Consul發現)。html

@EnableDiscoveryClient

Spring Cloud Commons提供@EnableDiscoveryClient註解,這將使用META-INF/spring.factories查找DiscoveryClient接口的實現。Discovery Client的實現將配置類添加到org.springframework.cloud.client.discovery.EnableDiscoveryClient鍵下的spring.factoriesDiscoveryClient實現的示例包括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 HealthIndicatorDiscoveryClient實現能夠經過實現DiscoveryHealthIndicator來參與,要禁用混合HealthIndicator,請設置spring.cloud.discovery.client.composite-indicator.enabled=false。基於DiscoveryClient的通用HealthIndicator是自動配置的(DiscoveryClientHealthIndicator)。要禁用它,請設置spring.cloud.discovery.client.health-indicator.enabled=false,要禁用DiscoveryClientHealthIndicatordescription字段,請設置spring.cloud.discovery.client.health-indicator.include-description=false,不然,它可能會像捲起的HealthIndicatordescription同樣冒出來。github

排序DiscoveryClient實例

DiscoveryClient接口擴展了Ordered,這在使用多個發現客戶端時頗有用,由於它容許你定義返回的發現客戶端的順序,相似於你能夠如何排序Spring應用程序加載的bean。默認狀況下,任何DiscoveryClient的順序都設置爲0,若是要爲自定義DiscoveryClient實現設置不一樣的順序,只需重寫getOrder()方法,以便它返回適合你的設置的值。除此以外,你還可使用屬性來設置Spring Cloud提供的DiscoveryClient實現的順序,其中包括ConsulDiscoveryClientEurekaDiscoveryClientZookeeperDiscoveryClient,爲此,你只需將spring.cloud.{clientIdentifier}.discovery.order(或Eureka的eureka.client.order)屬性設置爲所需的值。web

ServiceRegistry

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

  • ZookeeperRegistrationZookeeperServiceRegistry一塊兒使用
  • EurekaRegistrationEurekaServiceRegistry一塊兒使用
  • ConsulRegistrationConsulServiceRegistry一塊兒使用

若是你使用的是ServiceRegistry接口,則須要爲正在使用的ServiceRegistry實現傳遞正確的Registry實現。apache

ServiceRegistry自動註冊

默認狀況下,ServiceRegistry實現會自動註冊正在運行的服務,要禁用該行爲,你能夠設置: @EnableDiscoveryClient(autoRegister=false)永久禁用自動註冊, spring.cloud.service-registry.auto-registration.enabled=false經過配置禁用行爲。bootstrap

ServiceRegistry自動註冊事件

當服務自動註冊時,將觸發兩個事件,第一個事件名爲InstancePreRegisteredEvent,在註冊服務以前觸發,第二個事件名爲InstanceRegisteredEvent,在註冊服務後觸發,你能夠註冊一個ApplicationListener來監聽並響應這些事件。

若是 spring.cloud.service-registry.auto-registration.enabled設置爲 false,則不會觸發這些事件。

Service Registry Actuator端點

Spring Cloud Commons提供/service-registry執行器端點,此端點依賴於Spring Application Context中的Registration bean,使用GET調用/service-registry返回Registration的狀態,將POST用於具備JSON體的同一端點會將當前Registration的狀態更改成新值,JSON體必須包含具備首選值的status字段。在更新狀態和爲狀態返回的值時,請參閱用於容許值的ServiceRegistry實現的文檔,例如,Eureka支持的狀態是UPDOWNOUT_OF_SERVICEUNKNOWN

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;
    }
}
再也不經過自動配置建立 RestTemplate bean,單個應用程序必須建立它。

URI須要使用虛擬主機名(即服務名稱,而不是主機名),Ribbon客戶端用於建立完整的物理地址,有關如何設置RestTemplate的詳細信息,請參見RibbonAutoConfiguration

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客戶端用於建立完整的物理地址。

重試失敗的請求

能夠將負載均衡的RestTemplate配置爲重試失敗的請求,默認狀況下,禁用此邏輯,你能夠經過將Spring Retry添加到應用程序的類路徑來啓用它。負載均衡的RestTemplate支持與重試失敗的請求相關的一些Ribbon配置值,你可使用client.ribbon.MaxAutoRetriesclient.ribbon.MaxAutoRetriesNextServerclient.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,請建立一個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

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用於建立完整的物理地址。

忽略網絡接口

有時,忽略某些命名的網絡接口以便從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()

HTTP客戶端工廠

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實現,此外,若是你提供類型爲HttpClientBuilderOkHttpClient.Builder的bean,則默認工廠使用這些構建器做爲返回到下游項目的構建器的基礎,你還能夠經過將spring.cloud.httpclientfactories.apache.enabledspring.cloud.httpclientfactories.ok.enabled設置爲false來禁用這些bean的建立。

啓用特性

Spring Cloud Commons提供/features執行器端點,此端點返回類路徑上可用的特性以及它們是否已啓用,返回的信息包括特性類型、名稱、版本和供應商。

特性類型

有兩種類型的'特性':抽象和命名。

抽象特性是定義接口或抽象類並建立實現(如DiscoveryClientLoadBalancerClientLockService)的特性,抽象類或接口用於在上下文中查找該類型的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 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屬性。


上一篇:Spring Cloud Context:應用程序上下文服務

下一篇:Spring Cloud Config快速入門

相關文章
相關標籤/搜索