天天看點

spring cloud 翻譯-3. Spring Cloud Commons: Common Abstractions

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 鍵。DiscoveryClient的例子包括Spring Cloud Netflix Eureka,Spring Cloud Consul Discovery和Spring Cloud Zookeeper Discovery。

預設情況下,DiscoveryClient的實作會使用遠端發現服務自動注冊本地Spring Boot伺服器。可以通過在@EnableDiscoveryClient 中設定autoRegister=false 來禁用此行為。

    @EnableDiscoveryClient 不再是必須的。你可以在類路徑下放置DiscoveryClient實作以使Spring Boot應用程式向服務發現伺服器注冊。

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的description字段,請設定spring.cloud.discovery.client.health-indicator.include-description = false。 否則,它可能會像卷起的HealthIndicator的描述一樣冒出來。

3.2 服務注冊

Commons現在提供ServiceRegistry接口,該接口提供諸如注冊(注冊)和登出(注冊)之類的方法,這些方法允許您提供自定義注冊服務。 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與ConsulRegistry一起使用

如果你使用的是ServiceRegistry接口,則需有為正在使用的ServiceRegistry實作傳遞正确的Registry實作。

3.2.1 ServiceRegistry 自動注冊

預設情況下,ServiceRegistry 自動注冊正在運作的服務。要禁止該行為,你可以設定:*@EnableDiscoveryClient(autoRegister=false)來永久禁止自動注冊。通過配置*.spring.cloud.service-registry.auto-registration.enabled=false 禁止該行為。

ServiceRegistry 自動注冊事件

當服務自動注冊時,将觸發兩個事件。 第一個事件名為InstancePreRegisteredEvent,在注冊服務之前觸發。 第二個事件名為InstanceRegisteredEvent,在注冊服務後觸發。 您可以注冊一個ApplicationListener來監聽并響應這些事件。

    ·如果spring.cloud.service-registry.auto-registration.enabled設定為false,則不會觸發這些事件。

3.2.2 服務注冊執行器端點

Spring Cloud Commons 提供 /Service-registry 執行器端點。此端點依賴于Spring Application Context中的Registration bean。使用GET調用/service-registry傳回注冊的狀态。使用POST和JSON體調用相同的端點更改目前注冊的狀态為新的值。JSON體必須包含預期值的狀态字段。關于在更新狀态時的允許值和狀态傳回值請參考所使用的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;
        }
    }
           

    警告:RestTemplate不再通過自動配置建立。個人應用程式必須自己建立。

URL需要使用虛拟主機名(即服務名稱,而不是主機名)。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);
        }
    }
           

URL需要使用虛拟主機名(即服務名稱,而不是主機名)。Ribbon用戶端用于建立完整的實體位址。

3.4.1 重試失敗請求

負載均衡的RestTemplate可以配置重試失敗請求。預設情況下,該邏輯是禁止的。你可以通過添加Spring Retry到你的應用程式的類路徑下來啟用它。負載均衡的RestTemplate擁有與重試失敗請求相關的一些Rinbbon配置值。你可以使用client.ribbon.MaxAutoRetries,client.ribbon.MaxAutoRetriesNextServer 與 client.ribbon.OkToRetryOnAllOperations 屬性。如果你想使用類路徑上的Spring Retry 來禁用重試邏輯,可以設定 spring.cloud.loadbalancer.retry.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("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。

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);
        }
    }
           

URL需要使用虛拟主機名(即服務名稱,而不是主機名)。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用戶端(ApacheHttppClientFactory)和OK HTTP用戶端(OkHttpClientFactory)提供bean。隻有OK HTTP jar 在了路徑上才會建立OkHttpClientFactory bean。另外,Spring Cloud Commons 為建立兩個用戶端使用的連接配接管理器提供bean:對應Apache HTTP用戶端的ApacheHttpClientConnectionMannagerFactory和對應OK HTTP用戶端的OkHttpClientConnectionPoolFactory。如果要自定義在下遊項目中HTTP用戶端的建立方式,可以提供自己的這些bean實作。另外,你可以提供類型為HttpClientBuilder或OkHttpClient.Builder的bean,預設工廠使用這些建構器作為傳回下遊工程的建構器的基礎。你也可以通過設定spring.cloud.httpclientfactories,apache.enabled 或 spring.cloud.httpclientfactories.ok.enabled 為false來禁用這些bean的建立。

2.9 啟用特性

Spring Cloud Commons 提供 /features 執行器端點。該端點傳回類路徑上可用的特性以及它們是否啟用。傳回的資訊包含特性類型,名稱,版本和供應商。

3.9.1 特性類型

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

抽象特性是接口或抽象類定義和實作建立所在的特性(總覺的哪裡怪怪的,原文:Abstract features are features where an interface or abstract class is defined and that an implementation the creates),如 DiscoveryClient,LoadBalancerClient 或LockService。抽象類或接口用于查找上下文中對應類型的bean。顯示的版本是bean.getClass().getPackage().getImplementionVersion()。

命名特性是它們所實作的沒有特定類的特性,諸如 "Circuit Breaker", "API Gateway", "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。

Part I. Cloud Native Applications 完!to be continued ······

繼續閱讀