使用 Consul 進行服務發現
如何啟用
要啟用 Consul 服務發現,請使用 group 為 org.springframework.cloud 且 artifact id 為 spring-cloud-starter-consul-discovery 的啟動器。有關使用當前 Spring Cloud 釋出版本設定構建系統的詳細資訊,請參閱 Spring Cloud 專案頁面。
向 Consul 註冊
當客戶端向 Consul 註冊時,它會提供自己的元資料,例如主機和埠、ID、名稱和標籤。預設情況下會建立一個 HTTP 檢查,Consul 每 10 秒訪問一次 /actuator/health 端點。如果健康檢查失敗,服務例項將被標記為關鍵。
Consul 客戶端示例
@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:
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 中。 |
從 Environment 中獲取的預設服務名稱、例項 ID 和埠分別是 ${spring.application.name}、Spring 上下文 ID 和 ${server.port}。
要停用 Consul Discovery Client,您可以將 spring.cloud.consul.discovery.enabled 設定為 false。當 spring.cloud.discovery.enabled 設定為 false 時,Consul Discovery Client 也會被停用。
要停用服務註冊,您可以將 spring.cloud.consul.discovery.register 設定為 false。
將管理註冊為獨立服務
當管理伺服器埠透過設定 management.server.port 屬性與應用程式埠不同時,管理服務將作為獨立於應用程式服務註冊。例如
spring:
application:
name: myApp
management:
server:
port: 4452
上述配置將註冊以下兩個服務
-
應用程式服務
ID: myApp Name: myApp
-
管理服務
ID: myApp-management Name: myApp-management
管理服務將從應用程式服務繼承其 instanceId 和 serviceName。例如
spring:
application:
name: myApp
management:
server:
port: 4452
spring:
cloud:
consul:
discovery:
instance-id: custom-service-id
serviceName: myprefix-${spring.application.name}
上述配置將註冊以下兩個服務
-
應用程式服務
ID: custom-service-id Name: myprefix-myApp
-
管理服務
ID: custom-service-id-management Name: myprefix-myApp-management
可以透過以下屬性進行進一步自定義
/** 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 應用程式中健康端點的預設位置。如果您使用非預設上下文路徑或 servlet 路徑(例如 server.servletPath=/foo)或管理端點路徑(例如 management.server.servlet.context-path=/admin),則即使對於 Actuator 應用程式,您也需要更改此設定。
Consul 用於檢查健康端點的間隔也可以配置。“10s”和“1m”分別表示 10 秒和 1 分鐘。
此示例說明了上述內容(有關更多選項,請參閱 附錄頁 中的 spring.cloud.consul.discovery.health-check-* 屬性)。
spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.server.servlet.context-path}/actuator/health
healthCheckInterval: 15s
您可以透過將 spring.cloud.consul.discovery.register-health-check 設定為 false 來完全停用 HTTP 健康檢查。
應用頭資訊
頭資訊可以應用於健康檢查請求。例如,如果您嘗試註冊一個使用 Vault 後端 的 Spring Cloud Config 伺服器
spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token: 6442e58b-d1ea-182e-cfa5-cf9cddef0722
根據 HTTP 標準,每個頭資訊可以有多個值,在這種情況下,可以提供一個數組
spring:
cloud:
consul:
discovery:
health-check-headers:
X-Config-Token:
- "6442e58b-d1ea-182e-cfa5-cf9cddef0722"
- "Some other value"
TTL 健康檢查
可以使用 Consul TTL 檢查 代替預設配置的 HTTP 檢查。主要區別在於應用程式向 Consul 代理傳送心跳訊號,而不是 Consul 代理嚮應用程式傳送請求。
應用程式傳送 ping 的間隔也可以配置。"10s" 和 "1m" 分別表示 10 秒和 1 分鐘。預設值為 30 秒。
此示例說明了上述內容(有關更多選項,請參閱 附錄頁 中的 spring.cloud.consul.discovery.heartbeat.* 屬性)。
spring:
cloud:
consul:
discovery:
heartbeat:
enabled: true
ttl: 10s
TTL 應用程式狀態
對於 Spring Boot Actuator 應用程式,其狀態由其可用的健康端點確定。當健康端點不可用時(無論是停用還是不是 Spring Boot Actuator 應用程式),它假定應用程式處於良好健康狀態。
查詢健康端點時,預設使用根 健康組。可以透過設定以下屬性來使用不同的健康組
spring:
cloud:
consul:
discovery:
heartbeat:
actuator-health-group: <your-custom-group-goes-here>
您可以透過設定以下屬性完全停用健康端點
spring:
cloud:
consul:
discovery:
heartbeat:
use-actuator-health: false
自定義 TTL 應用程式狀態
如果您想配置自己的應用程式狀態機制,只需實現 ApplicationStatusProvider 介面
@Bean
public class MyCustomApplicationStatusProvider implements ApplicationStatusProvider {
public CheckStatus currentStatus() {
return yourMethodToDetermineAppStatusGoesHere();
}
}
並將其提供給應用程式上下文
@Bean
public CustomApplicationStatusProvider customAppStatusProvider() {
return new MyCustomApplicationStatusProvider();
}
Actuator 健康指標
如果服務例項是 Spring Boot Actuator 應用程式,則可以提供以下 Actuator 健康指標。
DiscoveryClientHealthIndicator
當 Consul 服務發現處於活動狀態時,會配置一個 DiscoverClientHealthIndicator 並使其可用於 Actuator 健康端點。有關配置選項,請參見 此處。
ConsulHealthIndicator
配置了一個指標來驗證 ConsulClient 的健康狀況。
預設情況下,它會檢索 Consul leader 節點狀態和所有已註冊的服務。在有許多已註冊服務的部署中,每次健康檢查都檢索所有服務可能會很昂貴。要跳過服務檢索並僅檢查 leader 節點狀態,請設定 spring.cloud.consul.health-indicator.include-services-query=false。
要停用該指標,請設定 management.health.consul.enabled=false。
| 當應用程式在 引導上下文模式(預設)下執行時,此指標被載入到引導上下文,並且不可用於 Actuator 健康端點。 |
元資料
Consul 支援服務的元資料。Spring Cloud 的 ServiceInstance 有一個 Map<String, String> metadata 欄位,它從服務的 meta 欄位填充。要填充 meta 欄位,請在 spring.cloud.consul.discovery.metadata 或 spring.cloud.consul.discovery.management-metadata 屬性上設定值。
spring:
cloud:
consul:
discovery:
metadata:
myfield: myvalue
anotherfield: anothervalue
上述配置將導致一個服務,其元欄位包含 myfield→myvalue 和 anotherfield→anothervalue。
生成的元資料
Consul 自動註冊將自動生成一些條目。
| 鍵 | 值 |
|---|---|
'group' |
屬性 |
'secure' |
如果屬性 |
屬性 |
屬性 |
舊版 Spring Cloud Consul 透過解析 spring.cloud.consul.discovery.tags 屬性填充 Spring Cloud Commons 中的 ServiceInstance.getMetadata() 方法。此功能不再受支援,請遷移到使用 spring.cloud.consul.discovery.metadata 對映。 |
使 Consul 例項 ID 唯一
預設情況下,Consul 例項使用與其 Spring 應用程式上下文 ID 相等的 ID 進行註冊。預設情況下,Spring 應用程式上下文 ID 為 ${spring.application.name}:comma,separated,profiles:${server.port}。在大多數情況下,這將允許同一服務的多個例項在同一臺機器上執行。如果需要進一步的唯一性,使用 Spring Cloud,您可以透過在 spring.cloud.consul.discovery.instanceId 中提供唯一識別符號來覆蓋此設定。例如
spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
有了這些元資料,並且在 localhost 上部署了多個服務例項,隨機值將起作用以使例項唯一。在 Cloudfoundry 中,vcap.application.instance_id 將在 Spring Boot 應用程式中自動填充,因此不需要隨機值。
查詢服務
使用負載均衡器
Spring Cloud 支援 Feign(一個 REST 客戶端構建器)以及 Spring RestTemplate,用於使用邏輯服務名稱/ID 而不是物理 URL 查詢服務。Feign 和支援服務發現的 RestTemplate 都利用 Spring Cloud LoadBalancer 進行客戶端負載均衡。
如果您想使用 RestTemplate 訪問服務 STORES,只需宣告
@LoadBalanced
@Bean
public RestTemplate loadbalancedRestTemplate() {
return new RestTemplate();
}
並像這樣使用它(注意我們如何使用 Consul 中的 STORES 服務名稱/ID,而不是完全限定的域名)
@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 是 STORES 服務所在的資料中心。
| Spring Cloud 現在還支援 Spring Cloud LoadBalancer。 |
使用 DiscoveryClient
您也可以使用 org.springframework.cloud.client.discovery.DiscoveryClient,它為發現客戶端提供了一個簡單的 API,不特定於 Netflix,例如
@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 目錄監控
Consul 目錄監控利用了 consul 監控服務 的能力。目錄監控發出一個阻塞的 Consul HTTP API 呼叫,以確定是否有任何服務已更改。如果有新的服務資料,則釋出一個心跳事件。
要更改 Config Watch 的呼叫頻率,請更改 spring.cloud.consul.config.discovery.catalog-services-watch-delay。預設值為 1000,以毫秒為單位。延遲是上次呼叫結束到下次呼叫開始之間的時間量。
要停用目錄監控,請設定 spring.cloud.consul.discovery.catalogServicesWatch.enabled=false。
該監控使用 Spring TaskScheduler 來排程對 consul 的呼叫。預設情況下,它是一個 ThreadPoolTaskScheduler,poolSize 為 1。要更改 TaskScheduler,請建立一個型別為 TaskScheduler 且名稱為 ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME 常量的 bean。