MicroProfile Health・服務健康嗎?
不曉得大家在開發 REST API 的時候,是否碰到過被反應服務出狀況,但是從 VM 監控上又看不出個所以然來,簡單的寫個 echo API 又不足以代表應用的實際負載程度,怎麼辦?
每個人應該會有不同的實作方法,首先要定義 API,然後實作各種檢查,最後一個一個匯總起來,最後透過 API 來判斷服務是否正常運作。
我相信大家也是這麼做的,這的確是很好的解決方案!但既然已經能自行解決,那麼 MicroProfile Health(後簡稱 MPHealth)是想幫助開發者解決什麼問題呢?
MPHealth 對開發者來說,主要是提供框架讓開發者可以省去定義 API 及開放 API 的困擾,只要專心在實作各種檢查就好。
存取服務健康 REST API
和 MPOpenAPI 一樣,部署應用啟動的同時,MPHealth 的機制已經啟動了,可以透過以下端點存取:
/health/ready
=> 服務是否準備就緒/health/live
=> 服務是否正常運作/health
=> 為了相容性而保留的舊版規格,會匯總ready
和live
的內容
實際上透過瀏覽器去連結會取得以下的 JSON:
{
"status": "UP",
"checks": []
}
因為沒有實作任何檢查,所以預設情況下,取得的資料就是 UP
正常運作的狀態。
實作健康檢查
依照 MPHealth 的定義,健康分為兩種:
- Readiness => 服務是否準備就緒,對應回
/health/ready
- Liveness => 服務是否正常運作,對應回
/health/live
規格中,並沒有要求或建議各別該實作哪些檢查,而是提供了便利實作這些檢查的 @annotation
和 API。判斷及實作 Readiness/Liveness 該具備哪些檢查邏輯,因應各應用需求會有所不同,這些就是我們開發人員的工作啦!
使用 MPHealth 實作健康檢查很簡單,只要把握以下幾個重點:
@Readiness
=> 用來標註是用作檢查是否準備就緒@Liveness
=> 用來標註是用作檢查是否正常運作HealthCheck
=> 用來實作健康檢查邏輯的interface
HealthCheckResponse
=> 健康檢查的回傳值
接下來,就來寫寫看!
// Java Code
@Readiness
@ApplicationScoped
public class MPHealthReadiness implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("Environment")
.withData("DB", true)
.withData("DB-Connection", 10)
.state(true)
.build();
}
}
是不是很簡單?
只要實作 HealthCheck
,把邏輯填入,然後標註 @Readiness
就會被列入準備就緒檢查。回傳數值中可以透過 withData(key, value)
加入各種資料,依照需求填入對準備就緒檢查有必要的數值。開發者撰寫邏輯來判斷是否要通過檢查並填入 state(up)
,true
代表通過,若不需要判斷也可以直接使用 up()
或 down()
來代表通過或失敗。
讓我們來看看呼叫 /health/ready
的結果:
{
"status": "UP",
"checks": [
{
"name": "Environment",
"status": "UP",
"data": {
"DB-Connection": "10",
"DB": "true"
}
}
]
}
這次因為有實作檢查,所以有數值了!內容就如同程式碼中所撰寫的呈現在結果之中。
在此說明幾個重點:
@Liveness
的用法和@Readiness
完全相同- 所有標註為
@Readiness
或@Liveness
的檢查,其結果會個別被匯總到對應的 REST API- 開發者可以去規劃怎麼管理檢查實作邏輯
- 不保證檢查被呼叫的順序,所以請確保單一檢查的完整性
一種檢查一個 class
,好似沒什麼問題,保有了最佳的彈性,但是一個檢查一個 class
有時在管理上也不是那麼的方便。若是這種情況,MPHealth 也提供了另一種實作方法來達成。
@ApplicationScoped
public class MPHealthPractice {
@Produces
@Liveness
public HealthCheck liveCheck1() {
return () -> HealthCheckResponse.named("I am lived")
.state(true)
.build();
}
@Produces
@Liveness
public HealthCheck liveCheck2() {
return new HealthCheck() {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("I am also lived")
.state(true).build();
}
};
}
}
用這種寫法就可以方便統一管理同一類型的數個檢查,實際上還是實作了 HealthCheck
再透過 CDI
的 @Produces
提供給 MPHealth 框架。
至於要採用 lambda
或 anonymous inner class
來撰寫,就端看個人。
REST API Status Code
在這要建議大家若要使用 MPHealth,請務必參照其中的 Response Codes and status mappings。
幫忙大家做個簡單的總結,若 HTTP Status
是:
200
=>UP
正常,包含 payload503
=>DOWN
異常,包含 payload500
=> 無法判斷的異常,無 payload
若要自己透過 REST API 來確認伺服器狀態,最簡單的判斷方式就是 200
才是正常情況,接下來才考慮各數值的狀態。
文末,做個簡單的結語,
MPHealth 提供了一個極容易使用的機制讓開發者實作服務的健康檢查,同時 REST API 的包裝也被包含在此機制之中。若有監控服務的需求,可以考慮採用此框架簡化開發邏輯。由於是公開規格,若廠商支援也可以順利自動整合。為了更穩健的提供服務,有何道理不採用呢?
by Arren Ping