66. 使用 Consul 进行服务发现
Service Discovery 是基于微服务的 architecture 的 key 原则之一。尝试手动配置每个 client 或某种形式的约定可能非常难以做到并且可能非常脆弱。 Consul 通过HTTP API和DNS提供服务发现服务。 Spring Cloud Consul 利用 HTTP API 进行服务注册和发现。这并不妨碍 non-Spring Cloud Applications 利用 DNS 接口。 Consul Agents 服务器在簇中运行,通过八卦协议进行通信并使用筏共识协议。
66.1 如何激活
要激活 Consul Service Discovery,请使用带有 group org.springframework.cloud
和 artifact id spring-cloud-starter-consul-discovery
的 starter。有关使用当前 Spring Cloud Release Train 设置 build 系统的详细信息,请参阅Spring Cloud 项目页面。
66.2 注册 Consul
当 client 向 Consul 注册时,它提供 meta-data 关于自身,例如 host 和 port,id,name 和 tags。默认情况下会创建 HTTP 校验,Consul 每 10 秒命中一次/health
端点。如果运行状况检查失败,则将服务实例标记为严重。
Example Consul client:
@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);
}
}
(i.e.完全正常 Spring Boot 应用程序)。如果 Consul client 位于localhost:8500
以外的其他位置,则需要 configuration 来定位 client。 例:
application.yml.
spring:
cloud:
consul:
host: localhost
port: 8500
如果使用Spring Cloud Consul Config,则需要将上述值放在
bootstrap.yml
而不是application.yml
中。
从Environment
获取的默认服务 name,instance id 和 port 分别是${spring.application.name}
,Spring Context ID 和${server.port}
。
要禁用 Consul Discovery Client,您可以将spring.cloud.consul.discovery.enabled
设置为false
。
要禁用服务注册,您可以将spring.cloud.consul.discovery.register
设置为false
。
66.3 HTTP 运行状况检查
Consul 实例的运行状况检查默认为“/health”,这是 Spring Boot Actuator application 中有用端点的默认位置。如果使用 non-default context 路径或 servlet 路径(e.g. server.servletPath=/foo
)或 management 端点路径(e.g. management.server.servlet.context-path=/admin
),则需要更改这些,即使对于 Actuator application 也是如此。还可以配置 Consul 用于检查运行状况端点的时间间隔。 “10s”和“1m”分别代表 10 秒和 1 分钟。 例:
application.yml.
spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.server.servlet.context-path}/health
healthCheckInterval: 15s
您可以通过设置management.health.consul.enabled=false
来禁用运行状况检查。
66.3.1 元数据和 Consul 标记
Consul 尚不支持服务元数据。 Spring Cloud 的ServiceInstance
有一个Map<String, String> metadata
字段。 Spring Cloud Consul 使用 Consul 标签来近似元数据,直到 Consul 正式支持元数据。具有key=value
形式的标签将被拆分并分别用作Map
key 和 value。没有相同=
符号的标签将同时用作 key 和 value。
application.yml.
spring:
cloud:
consul:
discovery:
tags: foo=bar, baz
上面的 configuration 将导致带有foo→bar
和baz→baz
的 map。
66.3.2 使 Consul 实例 ID 唯一
默认情况下,consul 实例注册的 ID 等于其 Spring Application Context ID。默认情况下,Spring Application Context ID 为${spring.application.name}:comma,separated,profiles:${server.port}
。对于大多数情况,这将允许一台服务的多个实例在一台机器上运行。如果需要进一步的唯一性,使用 Spring Cloud 可以通过在spring.cloud.consul.discovery.instanceId
中提供唯一标识符来覆盖它。例如:
application.yml.
spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
有了这个元数据,并且在 localhost 上部署了多个服务实例,随机 value 将在那里启动以使该实例唯一。在 Cloudfoundry 中,vcap.application.instance_id
将自动填充在 Spring Boot application 中,因此不需要随机 value。
66.4 查找服务
66.4.1 使用 Ribbon
Spring Cloud 支持假装(REST 客户端构建器),也支持Spring RestTemplate使用逻辑服务 names/ids 而不是物理 URL 查找服务。 Feign 和 discovery-aware RestTemplate 都使用带进行 client-side 负载平衡。
如果要使用 RestTemplate 访问服务 STORES,只需声明:
@LoadBalanced
@Bean
public RestTemplate loadbalancedRestTemplate() {
new RestTemplate();
}
并像这样使用它(注意我们如何使用来自 Consul 的 STORES 服务 name/id 而不是完全限定的域名):
@Autowired
RestTemplate restTemplate;
public String getFirstProduct() {
return this.restTemplate.getForObject("https://STORES/products/1", String.class);
}
如果您在多个数据中心中有 Consul 群集,并且您想要访问另一个数据中心中的服务,则仅服务 name/id 是不够的。在这种情况下,您使用 property spring.cloud.consul.discovery.datacenters.STORES=dc-west
,其中STORES
是服务 name/id,dc-west
是 STORES 服务所在的数据中心。
66.4.2 使用 DiscoveryClient
您还可以使用org.springframework.cloud.client.discovery.DiscoveryClient
为发现客户端提供一个简单的 API,该 API 不是特定于 Netflix,e.g.
@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;
}
66.5 Consul Catalog Watch
Consul 目录 Watch 利用 consul watch 服务的能力。 Catalog Watch 进行阻塞 Consul HTTP API 调用以确定是否有任何服务已更改。如果有新的服务数据,则发布 Heartbeat Event。
要更改调用 Config Watch 的频率,请更改spring.cloud.consul.config.discovery.catalog-services-watch-delay
。默认的 value 是 1000,以毫秒为单位。延迟是上一次调用结束和下一次调用开始后 time 的数量。
要禁用 Catalog Watch set spring.cloud.consul.discovery.catalogServicesWatch.enabled=false
。
watch 使用 Spring TaskScheduler
来安排对 consul 的调用。默认情况下,它是一个ThreadPoolTaskScheduler
,其poolSize
为 1.要更改TaskScheduler
,请创建一个ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME
类型