運行階段執(zhí)行健康檢查的目的是為了從Eureka服務(wù)器注冊表中識別并刪除不可訪問的微服務(wù),Eureka 服務(wù)器并不是向客戶端發(fā)送心跳請求,而是反過來,Eureka 客戶端將心跳發(fā)送到Eureka服務(wù)器,讓服務(wù)器了解其狀態(tài)。
這些心跳機制就需要在微服務(wù)嵌入一個客戶端,用來發(fā)送心跳,但是客戶端本身必須確定其健康狀態(tài),而且Eureka服務(wù)器必須為客戶端公開一些REST操作以讓其發(fā)布心跳。
Eureka服務(wù)器向客戶端公開下面資源以讓其發(fā)送心跳:
PUT /eureka/apps/{app id}/{instance id}?status={status}
{instance id}采用 hostname:app id:port,其中app id代表標(biāo)識唯一的Eureka客戶端實例,Eureka服務(wù)器會識別一些狀態(tài)數(shù)值:UP; DOWN; STARTING; OUT_OF_SERVICE; UNKNOWN.
客戶端發(fā)送心跳時的URL如下:
PUT /eureka/apps/ORDER-SERVICE/localhost:order-service:8886?status=UP
Eureka服務(wù)器收到心跳請求后,會續(xù)訂該實例的租約。如果是第一個心跳,則Eureka服務(wù)器以404響應(yīng),之后客戶端必須首先發(fā)送注冊請求。
此外, Eureka服務(wù)器公開以下操作以允許健康狀態(tài)的修改和刪除:
PUT /eureka/apps/{app id}/{instance id}/status?value={status}
DELETE /eureka/apps/{app id}/{instance id}/status
修改操作(即PUT上面的操作)是用于手動獲取健康的實例OUT_OF_SERVICE時操作,或者使用Asgard等管理工具 (暫時禁止某些實例的流量)時操作。
這種修改操作對于“紅/黑”部署非常有用,在這種情況下,你可以在一段時間內(nèi)運行較舊版本的微服務(wù)(如果新版本不穩(wěn)定,則可以輕松回滾到舊版本)。完成新版本的部署并且新版本開始為請求提供服務(wù)后,可以讓舊版本OUT_OF_SERVICE(但不會讓他們停止)暫停提供請求服務(wù)。即
PUT /eureka/apps/ORDER-SERVICE/localhost:order-service:8886/statusvalue=OUT_OF_SERVICE
上面修改的狀態(tài)也可以被丟棄,我們可以指示讓Eureka服務(wù)器開始遵守實例本身發(fā)布的狀態(tài),如下所示:
DELETE /eureka/apps/ORDER-SERVICE/localhost:order-service:8886/status
當(dāng)您發(fā)現(xiàn)微服務(wù)的新版本不穩(wěn)定并且您希望獲得舊版本(即已經(jīng)被打上OUT_OF_SERVICE標(biāo)記的版本)以開始提供請求時,上述辦法非常有用。
Eureka客戶端自我診斷
Eureka客戶端(或服務(wù)器)都是不調(diào)用/health端點來確定實例的健康狀態(tài),Eureka實例的運行狀況由HealthCheckHandler實現(xiàn)確定,只要應(yīng)用程序正在運行,默認(rèn)情況下HealthCheckHandler始終會通知應(yīng)用程序處于某種 UP 狀態(tài)。
Eureka允許通過EurekaClient#registerHealthCheck()API 插入自定義的HealthCheckHandlers,如果在Spring Cloud設(shè)置了以下屬性,則會注冊一個新的Spring自己的處理程序EurekaHealthCheckHandler:
eureka.client.healthcheck.enabled=true
該EurekaHealthCheckHandler匯總了多個健康指標(biāo),如健康狀況:
DiskSpaceHealthIndicator RefreshScopeHealthIndicator HystrixHealthIndicator它將這些狀態(tài)會映射到Eureka支持的狀態(tài)之一,之后被映射后的狀態(tài)將通過心跳傳播到Eureka服務(wù)器。
Eureka客戶端健康端點
Eureka客戶端在向服務(wù)器注冊時會在其POST的內(nèi)容中加入healthCheckUrl ,這個healthCheckUrl的值是由以下實例屬性計算得出:
eureka.instance.health-check-url
eureka.instance.health-check-url-path
.health-check-url-path的默認(rèn)值是 /health,這是Springboot默認(rèn)專門用于檢查健康的actuator端點,除非.heath-check-url被專門配置了。
如果實現(xiàn)自定義健康狀況端點或更改默認(rèn)健康檢查路徑,則應(yīng)配置這些屬性:
如果更改默認(rèn)健康端點;
endpoints.health.path=/new-heath
# either relative path
eureka.instance.health-check-url-path=${endpoints.health.path}
# or absolute path
eureka.instance.health-check-url=http://${eureka.hostname}:${server.port}/${endpoints.health.path}
如果你引入一個 management.context-path
management.context-path=/admin
# either relative path
eureka.instance.health-check-url-path=${management.context-path}/health
# or absolute path
eureka.instance.health-check-url=http://${eureka.hostname}:${server.port}/${management.context-path}/health
健康狀況的試驗
Eureka服務(wù)器并不關(guān)心客戶端的狀態(tài) - 它只記錄客戶端狀態(tài),當(dāng)有人查詢其注冊表時,它也會發(fā)布客戶的健康狀況。即
GET /eureka/apps/ORDER-SERVICE
<application>
<name>DISCOVERY-EUREKA-CLIENT</name>
<instance>
<instanceId>localhost:discovery-eureka-client:8886</instanceId>
<ipAddr>192.168.1.6</ipAddr>
<port>8886</port>
<status>UP</status>
<overriddenstatus>UP</overriddenstatus>
<healthCheckUrl>http://localhost:8886/health</healthCheckUrl>
...
...
</instance>
</application>
這個響應(yīng)有三個與健康有關(guān)的重要信息: status 、overridenstatus和healthCheckUrl
status 是Eureka實例本身發(fā)布的健康狀況。 overriddenstatus 是手動或通過工具強制執(zhí)行的健康狀態(tài)。比如PUT /eureka/apps/{app id}/instance id}/status?value={status}操作用于修改發(fā)布的狀態(tài),那么status和overriddenstatus都將變更為新的狀態(tài)。 healthCheckUrl 是客戶端公開GET其健康狀態(tài)的端點。其他工具則可以利用這些健康信息:
客戶端負(fù)載平衡器(如Ribbon)可以做出負(fù)載平衡決策 : Ribbon 讀取 status 屬性并僅使用具有UP 負(fù)載平衡狀態(tài)的實例 。但是,Ribbon不會調(diào)用 healthCheckUrl, 而是依賴于注冊表中可用的、已發(fā)布實例狀態(tài)。
像Asgard這樣的部署工具可以做出部署決策 - 在滾動部署期間,Asgard部署了一個新版本的微服務(wù),在 部署其余實例之前一直等待當(dāng)前實例轉(zhuǎn)換到UP 狀態(tài)。但是,status Asgard 不是依賴于注冊表中可用的實例狀態(tài)(即屬性),而是 通過調(diào)用 healthCheckUrl來了解實例狀態(tài) ,這可能是因為status 屬性的值可能會變得陳舊(因為它取決于下一節(jié)中描述的幾個因素),但在這種情況下,實時健康狀態(tài)很重要,以避免部署延遲。
健康狀況的準(zhǔn)確性
由于下面列出的原因,Eureka服務(wù)器注冊表健康狀況的并不總是準(zhǔn)確的。
CAP中的AP - 由于Eureka在CAP定理方面定位于高度可用的系統(tǒng),因此在網(wǎng)絡(luò)分區(qū)期間,集群Eureka服務(wù)器之間的信息可能不一致。 服務(wù)器響應(yīng)緩存 - Eureka服務(wù)器維護(hù)一個響應(yīng)緩存,默認(rèn)情況下每30秒更新一次。因此,實際上在 GET /eureka/apps/{app id}/ 響應(yīng)中出現(xiàn) UP 的實例可能已經(jīng)DOWN 了 。 定期調(diào)度心跳 - 由于客戶端默認(rèn)情況下每30秒發(fā)送一次心跳,因此服務(wù)器注冊表中實例的運行狀況可能不準(zhǔn)確。 自我保護(hù) - 當(dāng)Eureka服務(wù)器沒有收到超過某個閾值的心跳時,它會停止失效注冊表中的客戶端,從而會使注冊表不準(zhǔn)確。因此,客戶端應(yīng)遵循適當(dāng)?shù)墓收限D(zhuǎn)移機制來補充這種不準(zhǔn)確性。
Eurake的自我保護(hù)機制
spring cloud專題