https://www.jdon.com/springcloud/eureka-health-monitoring.html
運行階段執行健康檢查的目的是為了從Eureka服務器注冊表中識別並刪除不可訪問的微服務,Eureka 服務器並不是向客戶端發送心跳請求,而是反過來,Eureka 客戶端將心跳發送到Eureka服務器,讓服務器了解其狀態。
這些心跳機制就需要在微服務嵌入一個客戶端,用來發送心跳,但是客戶端本身必須確定其健康狀態,而且Eureka服務器必須為客戶端公開一些REST操作以讓其發布心跳。
Eureka服務器向客戶端公開下面資源以讓其發送心跳:
PUT /eureka/apps/{app id}/{instance id}?status={status}
{instance id}采用 hostname:app id:port,其中app id代表標識唯一的Eureka客戶端實例,Eureka服務器會識別一些狀態數值:UP; DOWN; STARTING; OUT_OF_SERVICE; UNKNOWN.
客戶端發送心跳時的URL如下:
PUT /eureka/apps/ORDER-SERVICE/localhost:order-service:8886?status=UP
Eureka服務器收到心跳請求后,會續訂該實例的租約。如果是第一個心跳,則Eureka服務器以404響應,之后客戶端必須首先發送注冊請求。
此外, Eureka服務器公開以下操作以允許健康狀態的修改和刪除:
PUT /eureka/apps/{app id}/{instance id}/status?value={status}
DELETE /eureka/apps/{app id}/{instance id}/status
修改操作(即PUT上面的操作)是用於手動獲取健康的實例OUT_OF_SERVICE時操作,或者使用Asgard等管理工具 (暫時禁止某些實例的流量)時操作。
這種修改操作對於“紅/黑”部署非常有用,在這種情況下,你可以在一段時間內運行較舊版本的微服務(如果新版本不穩定,則可以輕松回滾到舊版本)。完成新版本的部署並且新版本開始為請求提供服務后,可以讓舊版本OUT_OF_SERVICE(但不會讓他們停止)暫停提供請求服務。即
PUT /eureka/apps/ORDER-SERVICE/localhost:order-service:8886/statusvalue=OUT_OF_SERVICE
上面修改的狀態也可以被丟棄,我們可以指示讓Eureka服務器開始遵守實例本身發布的狀態,如下所示:
DELETE /eureka/apps/ORDER-SERVICE/localhost:order-service:8886/status
當您發現微服務的新版本不穩定並且您希望獲得舊版本(即已經被打上OUT_OF_SERVICE標記的版本)以開始提供請求時,上述辦法非常有用。
Eureka的健康檢查
客戶端需要在工程中添加組件依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>1.5.14.RELEASE</version> </dependency>
然后在配置文件里面加上健康狀態檢查配置:
eureka: client: healthcheck: enabled: true
這時,啟動自己的服務,通過http://localhost:port/health訪問就可以得到服務的健康狀態信息:
{"description":"Composite Discovery Client","status":"UP"}
當這個配置設置為false時,服務將不會把健康狀態傳遞給Eureka,那么Eureka就不會再更新Status信息,但是此時仍能夠通過上面的地址獲取這個真實的狀態信息。
應用狀態的取值:UP,DOWN,OUT_OF_SERVICE,UNKNOWN等;只有標記為UP的微服務會被請求;
通過在application.yml中配置eureka.client.healthcheck.enabled = true,應用程序會將自己Spring Boot Actuator的/heath端點的健康狀態傳播到Eureka Server
這里的/health檢查包括下面這些,其中還包括redis、mysql、hystrix等監控的檢查:
如健康狀況:
- DiskSpaceHealthIndicator
- RefreshScopeHealthIndicator
- HystrixHealthIndicator
它將這些狀態會映射到Eureka支持的狀態之一,之后被映射后的狀態將通過心跳傳播到Eureka服務器。
列如一個應用實例在監控檢查的時候發現當前的磁盤空間不夠用了,就會通過心跳傳遞給Eureka服務器,這里時候你在Eureka服務器查詢到當前應用實例的狀態就是down狀態
其他應用通過Eureka服務器獲得當前應用實例的狀態就是down,就無法訪問改應用實例,應用實例只有up狀態才能訪問
Erueka狀態變更說明
http://www.seotest.cn/jishu/41663.html
STARTING : 表示服務正在啟動中
DOWN: 表示服務已經宕機,無法繼續提供服務
UP : 服務正常運行
OUT_OF_SERVICE : 不再提供服務,其他的Eureka Client將調用不到該服務,一般有人為的調用接口設置的,如:強制下線。
UNKNOWN: 未知狀態
容器啟動
在容器剛剛啟動,實例化instance信息的時候,默認狀態為STARTING
在Eureka Client端,有一個40秒執行一次的定時任務,會定時的去掃描自身的信息,查看自身信息是否發生改變,
其中就有一個對狀態的檢測,這個時候,如果設置了健康檢查器,那么會以健康檢查的結果為准,判斷當前實例的
狀態,然后會通過心跳實例的最新狀態重新注冊到Eureka上面去。
Eureka客戶端健康端點
Eureka客戶端在向服務器注冊時會在其POST的內容中加入healthCheckUrl ,這個healthCheckUrl的值是由以下實例屬性計算得出:
eureka.instance.health-check-url
eureka.instance.health-check-url-path
如果實現自定義健康狀況端點或更改默認健康檢查路徑,則應配置這些屬性:
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服務器並不關心客戶端的狀態 - 它只記錄客戶端狀態,當有人查詢其注冊表時,它也會發布客戶的健康狀況。即
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>
這個響應有三個與健康有關的重要信息: status 、overridenstatus和healthCheckUrl
- status 是Eureka實例本身發布的健康狀況。
- overriddenstatus 是手動或通過工具強制執行的健康狀態。比如PUT /eureka/apps/{app id}/instance id}/status?value={status}操作用於修改發布的狀態,那么status和overriddenstatus都將變更為新的狀態。
- healthCheckUrl 是客戶端公開GET其健康狀態的端點。
其他工具則可以利用這些健康信息:
-
客戶端負載平衡器(如Ribbon)可以做出負載平衡決策 : Ribbon 讀取 status 屬性並僅使用具有UP 負載平衡狀態的實例 。但是,Ribbon不會調用 healthCheckUrl, 而是依賴於注冊表中可用的、已發布實例狀態。如一個應用實例在Eureka在服務器上面的狀態是down,Ribbon從Eureka服務器上面讀取實例的狀態是down,那么Ribbon就不會調用down狀態的應用實例,但是你直接通過postman請求改應用實例是可以的,但是通過Ribbon是無法遠程訪問改應用實例的
健康狀況的准確性
由於下面列出的原因,Eureka服務器注冊表健康狀況的並不總是准確的。
- CAP中的AP - 由於Eureka在CAP定理方面定位於高度可用的系統,因此在網絡分區期間,集群Eureka服務器之間的信息可能不一致。
- 服務器響應緩存 - Eureka服務器維護一個響應緩存,默認情況下每30秒更新一次。因此,實際上在 GET /eureka/apps/{app id}/ 響應中出現 UP 的實例可能已經DOWN 了 。
- 定期調度心跳 - 由於客戶端默認情況下每30秒發送一次心跳,因此服務器注冊表中實例的運行狀況可能不准確。
- 自我保護 - 當Eureka服務器沒有收到超過某個閾值的心跳時,它會停止失效注冊表中的客戶端,從而會使注冊表不准確。
因此,客戶端應遵循適當的故障轉移機制來補充這種不准確性。
Spring boot admin 節點狀態一直為DOWN的排查(忽略某一個節點的健康檢查)
某個應用實例運行成功后服務節點一直顯示為DOWN,訪問 http://127.0.0.1:8081/actuator/health健康檢查端點返回值如下
可以看出redis 宕機了,但其實我項目本身沒有使用redis。,我們可以在應該實例的健康檢查中忽略redis的檢查,這里在eureka服務器上面改應用實例的狀態就不是down狀態了。
在顯示DOWN的客戶端添加如下配置(忽略redis的健康檢查):
spring: profiles: active: dev management: health: redis: enabled: false endpoint: health: show-details: always endpoints: web: exposure: include: "*" server: port: 8081
在spring boot admin監控中,一個應用下面存在3個應用實例,只要其中的一個應用實例的狀態為down,那么該應用的狀態就是down只要其中一個監控內容為DOWN,則該節點的總體狀態就為DOWN