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