使用 Consul 進行服務發現
如何啟用
若要啟用 Consul 服務發現,請使用群組為 org.springframework.cloud
和 artifact id 為 spring-cloud-starter-consul-discovery
的 starter。請參閱 Spring Cloud 專案頁面,以取得使用目前 Spring Cloud Release Train 設定建置系統的詳細資訊。
向 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 中。 |
預設服務名稱、實例 ID 和端口,取自 Environment
,分別為 ${spring.application.name}
、Spring Context 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
上述組態將註冊以下 2 個服務
-
應用程式服務
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}
上述組態將註冊以下 2 個服務
-
應用程式服務
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 應用程式中健康端點的預設位置。如果您使用非預設的 context path 或 servlet path (例如 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 Backend 的 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 Agent 發送心跳訊號,而不是 Consul Agent 向應用程式發送請求。
應用程式用於發送 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 領導節點狀態和所有已註冊的服務。在部署了許多已註冊服務的環境中,每次健康檢查都檢索所有服務可能成本很高。若要跳過服務檢索並僅檢查領導節點狀態,請設定 spring.cloud.consul.health-indicator.include-services-query=false
。
若要停用指示器,請設定 management.health.consul.enabled=false
。
當應用程式在 bootstrap context 模式 (預設) 下執行時,此指示器會載入到 bootstrap context 中,並且在 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
上述組態將產生一個服務,其 meta 欄位包含 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 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: 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
,它為不特定於 Netflix 的發現用戶端提供了一個簡單的 API,例如
@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 監看服務 的能力。Catalog Watch 進行阻塞式 Consul HTTP API 呼叫,以判斷是否有任何服務發生變更。如果存在新的服務資料,則會發佈 Heartbeat Event。
若要變更呼叫 Config Watch 的頻率,請變更 spring.cloud.consul.config.discovery.catalog-services-watch-delay
。預設值為 1000,單位為毫秒。延遲是前一次調用結束後到下一次調用開始之間的時間量。
若要停用 Catalog Watch,請設定 spring.cloud.consul.discovery.catalogServicesWatch.enabled=false
。
watch 使用 Spring TaskScheduler
來排程對 Consul 的呼叫。預設情況下,它是 ThreadPoolTaskScheduler
,其 poolSize
為 1。若要變更 TaskScheduler
,請建立一個類型為 TaskScheduler
的 bean,並以 ConsulDiscoveryClientConfiguration.CATALOG_WATCH_TASK_SCHEDULER_NAME
常數命名。