服务发现与 Consul

服务发现是微服务架构中的关键原则之一。手动为每个客户端配置或采用某种约定方式非常困难,且极易变得脆弱。Consul 通过 HTTP APIDNS 提供服务发现功能。Spring Cloud Consul 利用 HTTP API 实现服务注册与发现。这并不妨碍非 Spring Cloud 应用程序使用 DNS 接口。Consul 代理服务器以 集群 方式运行,并通过 Gossip 协议 进行通信,同时采用 Raft 共识协议spring-doc.cadn.net.cn

如何激活

要激活 Consul 服务发现,请使用组 org.springframework.cloud 和工件 ID spring-cloud-starter-consul-discovery 的Starters。有关如何使用当前 Spring Cloud 发行版列车配置构建系统的详细信息,请参阅 Spring Cloud 项目页面spring-doc.cadn.net.cn

注册到 Consul

当客户端向 Consul 注册时,它会提供有关自身的信息,例如主机和端口、ID、名称和标签。默认情况下,Consul 会创建一个 HTTP 检查,每 10 秒访问一次 /actuator/health 端点。如果健康检查失败,该服务实例将被标记为“严重”(critical)。spring-doc.cadn.net.cn

示例 Consul 客户端:spring-doc.cadn.net.cn

@SpringBootApplication
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello world";
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

(即完全正常的 Spring Boot 应用)。如果 Consul 客户端位于 localhost:8500 以外的其他位置,则需要配置以定位客户端。示例:spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      host: localhost
      port: 8500
如果您使用 Spring Cloud Consul Config,并且已设置 spring.cloud.bootstrap.enabled=truespring.config.use-legacy-processing=true 或使用 spring-cloud-starter-bootstrap,则上述值需要放置在 bootstrap.yml 中,而不是 application.yml

默认服务名、实例ID和端口分别来自Environment,分别为${spring.application.name}(Spring上下文ID)和${server.port}spring-doc.cadn.net.cn

要禁用 Consul 发现客户端,可将 spring.cloud.consul.discovery.enabled 设置为 false。当 spring.cloud.discovery.enabled 设置为 false 时,Consul 发现客户端也会被禁用。spring-doc.cadn.net.cn

要禁用服务注册,您可以将 spring.cloud.consul.discovery.register 设置为 falsespring-doc.cadn.net.cn

注册管理为独立服务

当管理服务器端口设置为不同于应用端口的值时(通过设置 management.server.port 属性),管理服务将作为与应用服务不同的独立服务进行注册。例如:spring-doc.cadn.net.cn

application.yml
spring:
  application:
    name: myApp
management:
  server:
    port: 4452

上述配置将注册以下两个服务:spring-doc.cadn.net.cn

ID: myApp
Name: myApp
ID: myApp-management
Name: myApp-management

管理服务将从应用服务继承其 instanceIdserviceName。例如:spring-doc.cadn.net.cn

application.yml
spring:
  application:
    name: myApp
management:
  server:
    port: 4452
spring:
  cloud:
    consul:
      discovery:
        instance-id: custom-service-id
        serviceName: myprefix-${spring.application.name}

上述配置将注册以下两个服务:spring-doc.cadn.net.cn

ID: custom-service-id
Name: myprefix-myApp
ID: custom-service-id-management
Name: myprefix-myApp-management

还可以通过以下属性进行进一步的自定义:spring-doc.cadn.net.cn

/** Port to register the management service under (defaults to management port) */
spring.cloud.consul.discovery.management-port

/** Suffix to use when registering management service (defaults to "management") */
spring.cloud.consul.discovery.management-suffix

/** Tags to use when registering management service (defaults to "management") */
spring.cloud.consul.discovery.management-tags

HTTP 健康检查

Consul 实例的健康检查默认路径为 "/actuator/health",这是 Spring Boot Actuator 应用中健康端点的默认位置。即使在使用 Actuator 的应用中,如果您使用了非默认的上下文路径或 Servlet 路径(例如 server.servletPath=/foo)或管理端点路径(例如 management.server.servlet.context-path=/admin),仍需对其进行修改。spring-doc.cadn.net.cn

Consul 用于检查健康端点的时间间隔也可以进行配置。"10s" 和 "1m" 分别表示 10 秒和 1 分钟。spring-doc.cadn.net.cn

此示例说明了上述内容(参见附录页面中的spring.cloud.consul.discovery.health-check-*属性以获取更多选项)。spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        healthCheckPath: ${management.server.servlet.context-path}/actuator/health
        healthCheckInterval: 15s

您可以将 HTTP 健康检查完全禁用,方法是设置 spring.cloud.consul.discovery.register-health-check=falsespring-doc.cadn.net.cn

应用标题

标头可以应用于健康检查请求。例如,如果您正尝试注册一个使用 Spring Cloud Config 服务器,并且该服务器采用 Vault 后端spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        health-check-headers:
          X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722

根据 HTTP 标准,每个头字段可以包含多个值,此时可提供一个数组:spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        health-check-headers:
          X-Config-Token:
            - "6442e58b-d1ea-182e-cfa5-cf9cddef0722"
            - "Some other value"

TTL健康检查

可以使用 Consul TTL 检查 替代默认配置的 HTTP 检查。主要区别在于,应用程序向 Consul 代理发送心跳信号,而不是 Consul 代理向应用程序发起请求。spring-doc.cadn.net.cn

应用程序用于发送 ping 的时间间隔也可以进行配置。“10s”和“1m”分别表示 10 秒和 1 分钟。默认值为 30 秒。spring-doc.cadn.net.cn

此示例说明了上述内容(参见附录页面中的spring.cloud.consul.discovery.heartbeat.*属性以获取更多选项)。spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        heartbeat:
          enabled: true
          ttl: 10s

TTL 应用程序状态

对于 Spring Boot Actuator 应用程序,其状态由可用的健康端点决定。当健康端点不可用(无论是已禁用还是非 Spring Boot Actuator 应用程序)时,系统将假设应用程序处于良好状态。spring-doc.cadn.net.cn

查询健康端点时,默认使用根健康组。可以通过设置以下属性来使用不同的健康组:spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        heartbeat:
          actuator-health-group: <your-custom-group-goes-here>

您可以完全禁用健康端点的使用,方法是设置以下属性:spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        heartbeat:
          use-actuator-health: false
自定义TTL应用状态

如果您希望配置自己的应用状态机制,只需实现 ApplicationStatusProvider 接口spring-doc.cadn.net.cn

MyCustomApplicationStatusProvider.java
@Bean
public class MyCustomApplicationStatusProvider implements ApplicationStatusProvider {
	public CheckStatus currentStatus() {
        return yourMethodToDetermineAppStatusGoesHere();
    }
}

并将其提供给应用上下文:spring-doc.cadn.net.cn

@Bean
public CustomApplicationStatusProvider customAppStatusProvider() {
     return new MyCustomApplicationStatusProvider();
}

Actuator 健康指标

如果服务实例是一个 Spring Boot Actuator 应用程序,它可能会提供以下 Actuator 健康指标。spring-doc.cadn.net.cn

DiscoveryClientHealthIndicator

当 Consul 服务发现处于激活状态时,会配置一个 DiscoverClientHealthIndicator 并将其提供给 Actuator 健康端点。
有关配置选项,请参见 此处spring-doc.cadn.net.cn

ConsulHealthIndicator

已配置一个指标,用于验证 ConsulClient 的健康状况。spring-doc.cadn.net.cn

默认情况下,它会检索 Consul 领导节点的状态以及所有已注册的服务。在拥有大量已注册服务的部署中,每次健康检查都检索所有服务可能会带来较高的开销。为跳过服务检索、仅检查领导节点状态,请将 spring.cloud.consul.health-indicator.include-services-query=false 设置为该值。spring-doc.cadn.net.cn

要禁用指示器,请设置 management.health.consul.enabled=falsespring-doc.cadn.net.cn

当应用程序在 引导程序上下文模式(默认)下运行时,此指示器被加载到引导程序上下文中,并且不向Actuator健康端点公开。

元数据

Consul 支持在服务上使用元数据。Spring Cloud 的 ServiceInstance 中的 Map<String, String> metadata 字段可以从服务的 meta 字段填充。为了填充 meta 字段,请在 spring.cloud.consul.discovery.metadataspring.cloud.consul.discovery.management-metadata 属性上设置值。spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        metadata:
          myfield: myvalue
          anotherfield: anothervalue

此配置将导致服务元字段包含myfield→myvalueanotherfield→anothervaluespring-doc.cadn.net.cn

生成元数据

Consul 自动注册将自动生成一些条目。spring-doc.cadn.net.cn

表 1。 自动生成元数据

<p>以下是原英文内容的中文翻译:</p> <p>小组</p>spring-doc.cadn.net.cn

属性spring.cloud.consul.discovery.instance-group。这个值只有当instance-group为空时才被生成。spring-doc.cadn.net.cn

安全spring-doc.cadn.net.cn

如果属性spring.cloud.consul.discovery.scheme等于'https',则为真,否则为假。spring-doc.cadn.net.cn

属性 spring.cloud.consul.discovery.default-zone-metadata-name,默认值为 'zone'spring-doc.cadn.net.cn

属性spring.cloud.consul.discovery.instance-zone。这个值只有当instance-zone为空时才被生成。spring-doc.cadn.net.cn

(body) { Older versions of Spring Cloud Consul populated the code 0 method from Spring Cloud Commons by parsing the code 1 property. This is no longer supported, please migrate to using the code 2 map. }

确保Consul实例ID唯一性

默认情况下,Consul 实例会使用与其 Spring Application Context ID 相等的ID。默认的Spring Application Context ID为${spring.application.name}:comma,separated,profiles:${server.port}。在大多数情况下,这将允许同一台机器上运行一个服务的多个实例。如果需要进一步的唯一性,使用Spring Cloud时,可以通过在spring.cloud.consul.discovery.instanceId中提供唯一标识符进行覆盖。例如:spring-doc.cadn.net.cn

application.yml
spring:
  cloud:
    consul:
      discovery:
        instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

使用此元数据,并在本地部署多个服务实例时,随机值将起作用以使实例唯一。在 Cloud Foundry 中,Spring Boot 应用程序会自动填充 vcap.application.instance_id,因此随机值将不再需要。spring-doc.cadn.net.cn

查找服务

使用负载均衡器

Spring Cloud 支持 Feign(一个 REST 客户端构建器)以及也支持 Spring RestTemplate 用于通过逻辑服务名称/ID 而不是物理 URL 查找服务。Feign 和基于服务发现的 RestTemplate 都利用 Spring Cloud LoadBalancer 用于客户端侧负载均衡。spring-doc.cadn.net.cn

如果您想使用 RestTemplate 访问服务 STORES,请简单地进行声明:spring-doc.cadn.net.cn

@LoadBalanced
@Bean
public RestTemplate loadbalancedRestTemplate() {
     return new RestTemplate();
}

和使用它,就像这样(注意,我们从Consul中使用STORES服务名/ id,而不是完全限定的域名):spring-doc.cadn.net.cn

@Autowired
RestTemplate restTemplate;

public String getFirstProduct() {
   return this.restTemplate.getForObject("https://STORES/products/1", String.class);
}

如果您在多个数据中心拥有Consul集群,并且想要访问另一个数据中心的服务,仅服务名称/ID是不够的。 在这种情况下,您使用属性spring.cloud.consul.discovery.datacenters.STORES=dc-west,其中STORES是服务名称/ID,而dc-west是要存储的服务所在的数据中心。spring-doc.cadn.net.cn

Spring Cloud 现在也提供了对的支持 Spring Cloud LoadBalancer

使用发现客户端

您也可以使用 org.springframework.cloud.client.discovery.DiscoveryClient,它提供了一个不特定于 Netflix 的简单API用于发现客户端,例如spring-doc.cadn.net.cn

@Autowired
private DiscoveryClient discoveryClient;

public String serviceUrl() {
    List<ServiceInstance> list = discoveryClient.getInstances("STORES");
    if (list != null && list.size() > 0 ) {
        return list.get(0).getUri();
    }
    return null;
}

Consul Catalog Watch

Consul 目录监视利用了 Consul 提供的服务监视功能。目录监视对 Consul 执行阻止的 HTTP API 调用,以确定是否有任何服务已更改。如果有新的服务数据,则会发布心跳事件。spring-doc.cadn.net.cn

要更改配置监视程序被调用的频率,请更改 0 。默认值为 1000,以毫秒为单位。延迟是上次调用结束和下次调用开始之间的延时。 spring-doc.cadn.net.cn

禁用Catalog Watch请将spring.cloud.consul.discovery.catalogServicesWatch.enabled=false设置为值。spring-doc.cadn.net.cn

此监视器使用 Spring TaskScheduler 来计划对 Consul 的调用。默认情况下,其值为 ThreadPoolTaskSchedulerpoolSize 为 1。若要更改此 TaskScheduler,请创建一个名为 TaskSchedulerConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME 常量。spring-doc.cadn.net.cn