3. Spring Cloud Commons:Common Abstractions

服务发现,负载平衡和断路器等模式适用于所有 Spring Cloud clients 都可以使用的 common 抽象层,独立于 implementation(e.g. 发现通过 Eureka 或 Consul)。

3.1 @EnableDiscoveryClient

Commons 提供@EnableDiscoveryClient annotation。这将通过META-INF/spring.factories查找DiscoveryClient接口的 implementations。 _ Discovery Client 的实现将在org.springframework.cloud.client.discovery.EnableDiscoveryClient key 下为spring.factories添加 configuration class。 DiscoveryClient __mplementations 的示例:Spring Cloud Netflix EurekaSpring Cloud Consul DiscoverySpring Cloud Zookeeper Discovery

默认情况下,DiscoveryClient的_i实现 auto-register 本地 Spring Boot 服务器与 remote 发现服务器。可以通过在@EnableDiscoveryClient中设置autoRegister=false来禁用此功能。

不再需要使用@EnableDiscoveryClient。只需在 classpath 上使用DiscoveryClient implementation 就可以使 Spring Boot application 向服务发现服务器注册。

3.1.1 健康指标

Commons _创建一个 Spring Boot HealthIndicatorDiscoveryClient __mplement 可以通过实现DiscoveryHealthIndicator来参与。要禁用复合HealthIndicator set spring.cloud.discovery.client.composite-indicator.enabled=false。基于DiscoveryClient的泛型HealthIndicator是 auto-configured(

3.2 ServiceRegistry

Commons _now 提供ServiceRegistry接口,提供register(Registration)deregister(Registration)等方法,允许您提供自定义注册服务。 Registration是标记界面。

@Configuration
@EnableDiscoveryClient(autoRegister=false)
public class MyConfiguration {
    private ServiceRegistry registry;

    public MyConfiguration(ServiceRegistry registry) {
        this.registry = registry;
    }

    // called via some external process, such as an event or a custom actuator endpoint
    public void register() {
        Registration registration = constructRegistration();
        this.registry.register(registration);
    }
}

每个ServiceRegistry implementation 都有自己的Registry implementation。

  • ZookeeperRegistrationZookeeperServiceRegistry一起使用

  • EurekaRegistrationEurekaServiceRegistry一起使用

  • ConsulRegistrationConsulServiceRegistry一起使用

如果您使用ServiceRegistry接口,则需要为正在使用的ServiceRegistry implementation 传递正确的Registry implementation。

3.2.1 ServiceRegistry Auto-Registration

默认情况下,ServiceRegistry implementation 将运行服务。要禁用该行为,有两种方法。您可以将@EnableDiscoveryClient(autoRegister=false)设置为永久禁用 auto-registration。您还可以设置spring.cloud.service-registry.auto-registration.enabled=false以通过 configuration 禁用该行为。

3.2.2 Service Registry Actuator 端点

Commons 提供/service-registry actuator 端点。此端点依赖于 Spring Application Context 中的Registration bean。通过 GET 调用/service-registry/instance-status将_return Registration的状态。使用String正文对相同端点的 POST 会将当前Registration的状态更改为新的 value。请参阅您正在使用的ServiceRegistry implementation 的文档,其中包含用于更新状态的允许值以及为状态恢复的值。

3.3 Spring RestTemplate 作为负载均衡器 Client

RestTemplate可以自动配置为使用 ribbon。要创建负载均衡RestTemplate创建RestTemplate @Bean并使用@LoadBalanced限定符。

不再通过 auto configuration 创建RestTemplate bean。它必须由单独的 applications 创建。

@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 需要使用虚拟 host name(即 service name,而不是 host name)。 Ribbon client 用于创建完整的物理地址。有关如何设置RestTemplate的详细信息,请参阅RibbonAutoConfiguration

3.3.1 重试失败的请求

可以将负载平衡RestTemplate配置为重试失败的请求。默认情况下,此逻辑被禁用,您可以通过将Spring 重试添加到 application 的 classpath 来启用它。负载平衡RestTemplate将支持与重试失败请求相关的一些 Ribbon configuration 值。如果您想在 class 路径上使用 Spring Retry 禁用重试逻辑,则可以设置spring.cloud.loadbalancer.retry.enabled=false。您可以使用的 properties 是client.ribbon.MaxAutoRetriesclient.ribbon.MaxAutoRetriesNextServerclient.ribbon.OkToRetryOnAllOperations。有关 properties 的作用的说明,请参阅Ribbon 文档

如果要在重试中实现BackOffPolicy,则需要创建类型的 bean,并

@Configuration
public class MyConfiguration {
    @Bean
    LoadBalancedBackOffPolicyFactory backOffPolciyFactory() {
        return new LoadBalancedBackOffPolicyFactory() {
            @Override
            public BackOffPolicy createBackOffPolicy(String service) {
        		return new ExponentialBackOffPolicy();
        	}
        };
    }
}

上面示例中的client应替换为 Ribbon client 的 name。

如果要在重试中添加一个或多个RetryListener,则需要创建类型的 bean,并_返回要用于给定服务的RetryListener array。

@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.4 多个 RestTemplate objects

如果你想要一个非负载均衡的RestTemplate,那么创建一个RestTemplate bean 并 inject 它正常。要在创建@Bean时使用@LoadBalanced限定符来访问负载均衡RestTemplate

请注意下面 example 中 plain RestTemplate声明上的@Primary annotation,以消除不合格的@Autowired注入的歧义。

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

如果您看到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.5 忽略网络接口

有时忽略某些命名的网络接口是有用的,因此可以从 Service Discovery 注册中排除它们(例如,在 Docker 容器中运行)。可以设置正则表达式列表,这将导致忽略所需的网络接口。以下 configuration 将忽略“docker0”接口和所有以“veth”开头的接口。

application.yml.

spring:
  cloud:
    inetutils:
      ignoredInterfaces:
        - docker0
        - veth.*

您还可以使用正则表达式列表强制仅使用指定的网络地址:

bootstrap.yml.

spring:
  cloud:
    inetutils:
      preferredNetworks:
        - 192.168
        - 10.0

您还可以强制仅使用站点本地地址。有关详细信息,请参阅Inet4Address.html.isSiteLocalAddress()什么是站点本地地址。

application.yml.

spring:
  cloud:
    inetutils:
      useOnlySiteLocalInterfaces: true

3.6 HTTP Client Factories

Spring Cloud Commons _provides beans for creating Apache HTTP clients(ApacheHttpClientFactory)以及 OK HTTP clients(OkHttpClientFactory)。只有在 classpath 上有 OK HTTP jar 时才会创建OkHttpClientFactory bean。另外,Spring Cloud Commons _provides beans 用于创建 clients 使用的连接_manage,ApacheHttpClientConnectionManagerFactory用于 Apache HTTP client,OkHttpClientConnectionPoolFactory用于 OK HTTP client。如果要自定义在下游项目中创建 HTTP clients 的方式,可以提供自己的 beans 实现。您还可以通过将spring.cloud.httpclientfactories.apache.enabledspring.cloud.httpclientfactories.ok.enabled设置为false来禁用这些 beans 的创建。