Service Discovery with Consul
服务发现是基于微服务架构的关键原则之一。尝试手工配置每个客户端或某种形式的约定是非常困难且容易出现的。Consul通过 HTTP API和 DNS提供服务发现服务。Spring Cloud Consul利用HTTP API进行服务注册和发现。这并不会阻止非Spring Cloud应用程序利用DNS界面。Consul Agent服务器在一个 cluster中运行,该服务器通过一个 gossip protocol来通信并使用 Raft consensus protocol。
Service Discovery is one of the key tenets of a microservice based architecture. Trying to hand configure each client or some form of convention can be very difficult to do and can be very brittle. Consul provides Service Discovery services via an HTTP API and DNS. Spring Cloud Consul leverages the HTTP API for service registration and discovery. This does not prevent non-Spring Cloud applications from leveraging the DNS interface. Consul Agents servers are run in a cluster that communicates via a gossip protocol and uses the Raft consensus protocol.
How to activate
如需激活Consul服务发现,请使用组为`org.springframework.cloud`且工件ID为`spring-cloud-starter-consul-discovery`的starter。请参阅 Spring Cloud Project page了解有关使用当前Spring Cloud Release Train设置构建系统 的详细信息。
To activate Consul Service Discovery use the starter with group org.springframework.cloud
and artifact id spring-cloud-starter-consul-discovery
. See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.
Registering with Consul
当一个客户端在Consul中注册时,它会提供有关其自己的元数据,如主机和端口、ID、名称和标签。默认创建一个 HTTP Check,该 HTTP Check使Consul每10秒针对一次`/actuator/health`端点。如果健康检查失败,服务实例将被标为临界值。
When a client registers with Consul, it provides meta-data about itself such as host and port, id, name and tags. An HTTP Check is created by default that Consul hits the /actuator/health
endpoint every 10 seconds. If the health check fails, the service instance is marked as critical.
示例 Consul 客户端:
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);
}
}
(即完全正常的 Spring Boot 应用程序)。如果 Consul 客户端位于 localhost:8500
以外,则需要配置以找到该客户端。示例:
(i.e. utterly normal Spring Boot app). If the Consul client is located somewhere other than localhost:8500
, the configuration is required to locate the client. Example:
spring: cloud: consul: host: localhost port: 8500
如果你使用 Spring Cloud Consul Config,并且设置了 spring.cloud.bootstrap.enabled=true
或 spring.config.use-legacy-processing=true
或使用 spring-cloud-starter-bootstrap
,则需要将上述值放在 bootstrap.yml
中,而不是 application.yml
。
If you use Spring Cloud Consul Config, and you have set spring.cloud.bootstrap.enabled=true
or spring.config.use-legacy-processing=true
or use spring-cloud-starter-bootstrap
, then the above values will need to be placed in bootstrap.yml
instead of application.yml
.
默认服务名、实例 ID 和端口,取自 Environment
,分别为 ${spring.application.name}
,Spring 上下文 ID 和 ${server.port}
。
The default service name, instance id and port, taken from the Environment
, are ${spring.application.name}
, the Spring Context ID and ${server.port}
respectively.
要禁用 Consul 发现客户端,可以将 spring.cloud.consul.discovery.enabled
设置为 false
。当 spring.cloud.discovery.enabled
设置为 false
时,也会禁用 Consul 发现客户端。
To disable the Consul Discovery Client you can set spring.cloud.consul.discovery.enabled
to false
. Consul Discovery Client will also be disabled when spring.cloud.discovery.enabled
is set to false
.
要禁用服务注册,可以将 spring.cloud.consul.discovery.register
设置为 false
。
To disable the service registration you can set spring.cloud.consul.discovery.register
to false
.
Registering Management as a Separate Service
当通过设置 management.server.port
属性将管理服务器端口设置为与应用程序端口不同的内容时,管理服务将被注册为独立于应用程序服务的单独服务。例如:
When management server port is set to something different than the application port, by setting management.server.port
property, management service will be registered as a separate service than the application service. For example:
spring: application: name: myApp management: server: port: 4452
上述配置将注册以下 2 个服务:
Above configuration will register following 2 services:
-
Application Service:
ID: myApp Name: myApp
-
Management Service:
ID: myApp-management Name: myApp-management
管理服务将从应用程序服务处继承其 instanceId
和 serviceName
。例如:
Management service will inherit its instanceId
and serviceName
from the application service. For example:
spring: application: name: myApp management: server: port: 4452 spring: cloud: consul: discovery: instance-id: custom-service-id serviceName: myprefix-${spring.application.name}
上述配置将注册以下 2 个服务:
Above configuration will register following 2 services:
-
Application Service:
ID: custom-service-id Name: myprefix-myApp
-
Management Service:
ID: custom-service-id-management Name: myprefix-myApp-management
可以通过以下属性进行进一步自定义:
Further customization is possible via following properties:
/** 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 Health Check
Consul 实例的运行状况检查默认为 "/actuator/health",这是 Spring Boot Actuator 应用程序中运行状况终结点的默认位置。即使对于 Actuator 应用程序,如果您使用非默认上下文路径或 servlet 路径(例如 server.servletPath=/foo
)或管理终结点路径(例如 management.server.servlet.context-path=/admin
),您都需要更改此设置。
The health check for a Consul instance defaults to "/actuator/health", which is the default location of the health endpoint in a Spring Boot Actuator application. You need to change this, even for an Actuator application, if you use a non-default context path or servlet path (e.g. server.servletPath=/foo
) or management endpoint path (e.g. management.server.servlet.context-path=/admin
).
Consul 用于检查运行状况终结点的间隔也可以进行配置。“10s”和“1m”分别代表 10 秒和 1 分钟。
The interval that Consul uses to check the health endpoint may also be configured. "10s" and "1m" represent 10 seconds and 1 minute respectively.
此示例说明了上述内容(有关更多选项,请参阅附录页面中的 spring.cloud.consul.discovery.health-check-*
属性: link:appendix.html)。
This example illustrates the above (see the spring.cloud.consul.discovery.health-check-*
properties in the appendix page for more options).
spring: cloud: consul: discovery: healthCheckPath: ${management.server.servlet.context-path}/actuator/health healthCheckInterval: 15s
您可以通过设置 spring.cloud.consul.discovery.register-health-check=false
完全禁用 HTTP 运行状况检查。
You can disable the HTTP health check entirely by setting spring.cloud.consul.discovery.register-health-check=false
.
Applying Headers
可以将标头应用于运行状况检查请求。例如,如果您尝试注册一个使用 Vault Backend的 Spring Cloud Config服务器:
Headers can be applied to health check requests. For example, if you’re trying to register a Spring Cloud Config server that uses Vault Backend:
spring: cloud: consul: discovery: health-check-headers: X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722
根据 HTTP 标准,每个头都可以有多个值,在这种情况下,可以提供一个数组:
According to the HTTP standard, each header can have more than one values, in which case, an array can be supplied:
spring: cloud: consul: discovery: health-check-headers: X-Config-Token: - "6442e58b-d1ea-182e-cfa5-cf9cddef0722" - "Some other value"
TTL Health Check
可以使用 Consul TTL Check来替换默认配置的 HTTP 检查。主要区别在于:应用程序会向 Consul 代理发送心跳信号,而不是 Consul 代理向应用程序发送请求。
A Consul TTL Check can be used instead of the default configured HTTP check. The main difference is that the application sends a heartbeat signal to the Consul agent rather than the Consul agent sending a request to the application.
应用程序用于发送 ping 的时间间隔也可以进行配置。“10s”和“1m”分别代表 10 秒和 1 分钟。默认值为 30 秒。
The interval the application uses to send the ping may also be configured. "10s" and "1m" represent 10 seconds and 1 minute respectively. The default is 30 seconds.
此示例说明了上述内容(有关更多选项,请参阅附录页面中的 spring.cloud.consul.discovery.heartbeat.*
属性: link:appendix.html)。
This example illustrates the above (see the spring.cloud.consul.discovery.heartbeat.*
properties in the appendix page for more options).
spring: cloud: consul: discovery: heartbeat: enabled: true ttl: 10s
TTL Application Status
对于 Spring Boot Actuator 应用程序,状态由其可用的运行状况终结点决定。当运行状况终结点不可用时(禁用或不是 Spring Boot Actuator 应用程序),它会假定应用程序处于运行状况良好。
For a Spring Boot Actuator application the status is determined from its available health endpoint. When the health endpoint is not available (either disabled or not a Spring Boot Actuator application) it assumes the application is in good health.
在查询运行状况端点时,默认使用根 health group。可以通过设置以下属性来使用不同的运行状况组:
When querying the health endpoint, the root health group is used by default. A different health group can be used by setting the following property:
spring: cloud: consul: discovery: heartbeat: actuator-health-group: <your-custom-group-goes-here>
您可以通过设置以下属性来完全禁用运行状况终结点:
You can disable the use of the health endpoint entirely by setting the following property:
spring: cloud: consul: discovery: heartbeat: use-actuator-health: false
Custom TTL Application Status
如果您想配置您自己的应用程序状态机制,只需实现 ApplicationStatusProvider
接口即可
If you want to configure your own application status mechanism, simply implement the ApplicationStatusProvider
interface
@Bean public class MyCustomApplicationStatusProvider implements ApplicationStatusProvider { public CheckStatus currentStatus() { return yourMethodToDetermineAppStatusGoesHere(); } }
并提供给应用程序上下文:
and make it available to the application context:
@Bean public CustomApplicationStatusProvider customAppStatusProvider() { return new MyCustomApplicationStatusProvider(); }
Actuator Health Indicator(s)
如果服务实例是 Spring Boot Actuator 应用程序,可以为它提供以下 Actuator 健康指标。
If the service instance is a Spring Boot Actuator application, it may be provided the following Actuator health indicators.
DiscoveryClientHealthIndicator
当Consul服务发现处于活动状态时,将配置一个 DiscoverClientHealthIndicator供执行器健康端点使用。请参阅 here以了解配置选项。
When Consul Service Discovery is active, a DiscoverClientHealthIndicator is configured and made available to the Actuator health endpoint. See here for configuration options.
ConsulHealthIndicator
将配置一个用于验证 ConsulClient
健康状况的指标。
An indicator is configured that verifies the health of the ConsulClient
.
默认情况下,它会检索 Consul 领导节点状态和所有已注册服务。在拥有许多注册服务的部署中,每次执行健康检查时检索所有服务都可能很耗时。要跳过服务检索并仅检查领导节点状态,请将 spring.cloud.consul.health-indicator.include-services-query=false
设为 false。
By default, it retrieves the Consul leader node status and all registered services.
In deployments that have many registered services it may be costly to retrieve all services on every health check.
To skip the service retrieval and only check the leader node status set spring.cloud.consul.health-indicator.include-services-query=false
.
要禁用指标,请将 management.health.consul.enabled=false
设为 false。
To disable the indicator set management.health.consul.enabled=false
.
当应用程序在 bootstrap context mode(默认值)中运行时,这个指示器被加载到引导上下文中,并且不会提供给 Actuator 健康端点。
When the application runs in bootstrap context mode (the default), this indicator is loaded into the bootstrap context and is not made available to the Actuator health endpoint.
Metadata
Consul 支持服务上的元数据。Spring Cloud 的 ServiceInstance
有一个 Map<String, String> metadata
字段,该字段从 services meta
字段填充。要填充 meta
字段,请在 spring.cloud.consul.discovery.metadata
或 spring.cloud.consul.discovery.management-metadata
属性上设置值。
Consul supports metadata on services. Spring Cloud’s ServiceInstance
has a Map<String, String> metadata
field which is populated from a services meta
field. To populate the meta
field set values on spring.cloud.consul.discovery.metadata
or spring.cloud.consul.discovery.management-metadata
properties.
spring: cloud: consul: discovery: metadata: myfield: myvalue anotherfield: anothervalue
上述配置会产生一个元字段包含 myfield→myvalue
和 anotherfield→anothervalue
的服务。
The above configuration will result in a service who’s meta field contains myfield→myvalue
and anotherfield→anothervalue
.
Generated Metadata
Consul 自动注册会自动生成几个条目。
The Consul Auto Registration will generate a few entries automatically.
Key | Value |
---|---|
'group' |
Property |
'secure' |
True if property |
Property |
Property |
旧版本的 Spring Cloud Consul 通过解析 spring.cloud.consul.discovery.tags
属性从 Spring Cloud Commons 填充了 ServiceInstance.getMetadata()
方法。不再支持此操作,请迁移到使用 spring.cloud.consul.discovery.metadata
映射。
Older versions of Spring Cloud Consul populated the ServiceInstance.getMetadata()
method from Spring Cloud Commons by parsing the spring.cloud.consul.discovery.tags
property. This is no longer supported, please migrate to using the spring.cloud.consul.discovery.metadata
map.
Making the Consul Instance ID Unique
默认情况下,一个 Consul 实例会以与其 Spring 应用程序上下文 ID 相等的 ID 进行注册。默认情况下,Spring 应用程序上下文 ID 是 ${spring.application.name}:comma,separated,profiles:${server.port}
。在大多数情况下,这样一来便可以在一台机器上运行一个服务的多个实例。如果需要进一步的唯一性,可以使用 Spring Cloud 通过在 spring.cloud.consul.discovery.instanceId
中提供一个唯一标识符来覆盖此唯一性。例如:
By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is ${spring.application.name}:comma,separated,profiles:${server.port}
. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in spring.cloud.consul.discovery.instanceId
. For example:
spring: cloud: consul: discovery: instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
有了此元数据,并在本地主机上部署了多个服务实例,那么随机值将发挥作用,让实例变得唯一。在 Cloudfoundry 中,vcap.application.instance_id
会在 Spring Boot 应用程序中自动填充,因此不需要随机值。
With this metadata, and multiple service instances deployed on localhost, the random value will kick in there to make the instance unique. In Cloudfoundry the vcap.application.instance_id
will be populated automatically in a Spring Boot application, so the random value will not be needed.
Looking up services
Using Load-balancer
Spring Cloud支持 Feign(REST 客户端生成器)和 Spring RestTemplate
,用于使用逻辑服务名称/ID查找服务,而不是物理URL。Feign和支持发现的RestTemplate都利用 Spring Cloud LoadBalancer进行客户端负载平衡。
Spring Cloud has support for Feign (a REST client builder) and also Spring RestTemplate
for looking up services using the logical service names/ids instead of physical URLs. Both Feign and the discovery-aware RestTemplate utilize Spring Cloud LoadBalancer for client-side load balancing.
如果你想使用 RestTemplate 访问服务商店,只需声明:
If you want to access service STORES using the RestTemplate simply declare:
@LoadBalanced @Bean public RestTemplate loadbalancedRestTemplate() { return new RestTemplate(); }
并像下面这样使用它(请注意我们是如何使用来自 Consul 的商店服务名称/ID 而不是完全限定的域名):
and use it like this (notice how we use the STORES service name/id from Consul instead of a fully qualified domainname):
@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
是商店服务所在的数据中心。
If you have Consul clusters in multiple datacenters and you want to access a service in another datacenter a service name/id alone is not enough. In that case
you use property spring.cloud.consul.discovery.datacenters.STORES=dc-west
where STORES
is the service name/id and dc-west
is the datacenter
where the STORES service lives.
Spring Cloud 现在还提供对 Spring Cloud LoadBalancer 的支持。 |
Spring Cloud now also offers support for Spring Cloud LoadBalancer. |
Using the DiscoveryClient
你还可以使用 org.springframework.cloud.client.discovery.DiscoveryClient
,它提供了一个适用于非特定于 Netflix 的发现客户端的简单 API,例如:
You can also use the org.springframework.cloud.client.discovery.DiscoveryClient
which provides a simple API for discovery clients that is not specific to 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; }
Consul Catalog Watch
Consul Catalog Watch利用consul来 watch services的能力。Catalog Watch执行一个阻塞Consul HTTP API调用以确定是否已更改任何服务。如果出现新的服务数据,将发布一个心跳事件。
The Consul Catalog Watch takes advantage of the ability of consul to watch services. The Catalog Watch makes a blocking Consul HTTP API call to determine if any services have changed. If there is new service data a Heartbeat Event is published.
要更改调用配置监视的频率,请更改 spring.cloud.consul.config.discovery.catalog-services-watch-delay
。默认值为 1000,单位为毫秒。延迟是上一次调用和下一次调用开始之间的时间间隔。
To change the frequency of when the Config Watch is called change spring.cloud.consul.config.discovery.catalog-services-watch-delay
. The default value is 1000, which is in milliseconds. The delay is the amount of time after the end of the previous invocation and the start of the next.
要禁用目录监视,请将 spring.cloud.consul.discovery.catalogServicesWatch.enabled=false
设为 false。
To disable the Catalog Watch set spring.cloud.consul.discovery.catalogServicesWatch.enabled=false
.
监视使用 Spring TaskScheduler
为调用 Consul 安排时间。默认情况下,它是一个拥有 1 个 poolSize
的 ThreadPoolTaskScheduler
。要更改 TaskScheduler
,请创建一个名为 ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME
常量的 TaskScheduler
类型 bean。
The watch uses a Spring TaskScheduler
to schedule the call to consul. By default it is a ThreadPoolTaskScheduler
with a poolSize
of 1. To change the TaskScheduler
, create a bean of type TaskScheduler
named with the ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME
constant.