寫在前面
HealthCheck 不僅是對應用程式內執行情況、資料流通情況進行檢查,還包括應用程式對外部服務或依賴資源的健康檢查。
健康檢查通常是以 暴露應用程式的HTTP端點 的形式實施,可用於配置健康探測的的場景有 :
容器或負載均衡器 探測應用狀態,執行既定策略,例如:容器探測到應用unhealthy可終止後續的滾動部署或者重啟容器;負載均衡器探測到例項unhealthy能將請求路由到健康的執行例項。對應用程式種依賴的第三方服務進行健康探測,比如redis、database、外部服務介面記憶體、硬碟、網路等物理依賴資源的探測HealthCheck提供對外暴露程式執行狀態的機制。
容器HEALTHCHECK指令一般情況下我們很容易知道容器 正在執行running , 但容器作為相對獨立的應用執行環境,有時候並不知道容器是否 以預期方式正確運作working
Dockerfile HEALTHCHECK指令提供了探測容器以預期工作的輪詢機制,輪詢內容可由應用自身決定。
具體而言:通過在容器內執行shell命令來探測容器健康狀態,以Shell命令的退出碼錶示容器健康狀態:
0 指示容器健康
1 指示容器不健康
2 指示不使用這個退出碼
// 可定義輪詢interval、探測超時timeout、 重試retries引數輪詢探測HEALTHCHECK [OPTIONS] CMD command
Every Linux or Unix command executed by the shell script or user has an exit status. Exit status is an integer number. 0 exit status means the command was successful without any errors. A non-zero (1-255 values) exit status means command was a failure.
linux shell執行成功,返回0;為對接Docker-HealcthCheck失敗退出碼1,要對Shell執行失敗返回退出碼1
對Web應用,自然會聯想到使用 curl命令訪問端點 去探測容器應用:
curl web端點成功,命令返回0;curl web端點失敗,命令返回1
// curl -f 表示請求失敗返回HEALTHCHECK --interval=5m --timeout=3s --retries=3 CMD curl -f http://localhost:5000/healthz || exit 1
探測命令在stdout或stderr輸出的任何內容會在容器Health Status中儲存,可通過docker inspect [ContainerId] 檢視HealthCheck狀態。
下面漸進式演示使用Docker平臺的HEALTHCHECK指令對接 ASP.NET Core程式的健康檢查能力。
ASP.NET Core實現HealthCheck端點ASPNET Core在2.2版本內建了健康檢查的能力:終端中介軟體(滿足該路徑的url請求,將會被該中介軟體處理)。
public void ConfigureServices(IServiceCollection services){ services.AddHealthChecks();} public void Configure(IApplicationBuilder app, IHostingEnvironment env){ app.UseHealthChecks("/healthcheck");}
Asp.NetCore 3.1將健康檢查整合在 EndPoints,請自行修改。
請求/healthcheck端點, 程式會進行健康檢查邏輯並響應輸出, 預設的行為:
① 對healthy、degraded狀態返回200 OK響應碼;對於unhealthy返回503 Service Unavailable響應碼
② 響應體只會包含簡單的HealthStatus列舉字串
作為企業級專案,存在對Web專案物理資源和服務依賴的健康檢查需求, 這裡我們為避免重複造輪子,引入了開源的力量。
開源社群對HealthCheck的支援開源的企業級AspNetCore.Diagnostics.HealthChecks系列元件,該系列元件支援多種物理資源和服務依賴的健康檢查,支援報告推送,支援友好的檢查報告UI(支援後臺輪詢檢查)、支援webhook通知。
下面的步驟演示了對web程式HTTP請求、Redis、Sqlite等服務進行健康檢查的端點配置
① 引入AspNetCore.HealthChecks.Redis 、 AspNetCore.HealthChecks.Sqlite nuget庫
② Startup.cs配置並啟用健康檢查
// 以下程式碼擷取自 Startup.ConfigureServices方法,對swagger服務地址、redis、sqlte進行健康檢查services.AddHealthChecks().AddAsyncCheck("Http", async () => { using (HttpClient client = new HttpClient()) { try { var response = await client.GetAsync("http://localhost:5000/swagger"); if (!response.IsSuccessStatusCode) { throw new Exception("Url not responding with 200 OK"); } } catch (Exception) { return await Task.FromResult(HealthCheckResult.Unhealthy()); } } return await Task.FromResult(HealthCheckResult.Healthy()); }) .AddSqlite( sqliteConnectionString: Configuration.GetConnectionString("sqlite"), healthQuery: "select count(*) as count from ProfileUsageCounters;", name: "sqlite", failureStatus: HealthStatus.Degraded, tags: new string[] { "db", "sqlite", "sqlite" } ) .AddRedis(Configuration.GetConnectionString("redis"), "redis", HealthStatus.Unhealthy, new string[] { "redis", "redis" }) .Services .AddMvc();// 以下程式碼擷取自Startup.Configure方法:啟用/healthz作為檢查端點 app.UseHealthChecks("/healthz").UseMvcWithDefaultRoute(); // 這裡仍然只會響應 200/503狀態碼+簡單的HealthStatus列舉值
再次強調,容器HealthCheck指令不關注Shell命令的執行過程, 只關注shell命令的執行結果
// docker-compose.yml檔案健康檢查 參考如下配置:healthcheck: test: curl -f http://localhost/healthcheck || exit 1 interval: 1m30s timeout: 10s retries: 3
HealthChecks-UI 了解一下
拋開Docker的HEALTHCHECK指令、負載均衡器的輪詢機制不談,我們的Web自身也可以進行 輪詢健康檢查並給出告警。
就我們上面的Web 例項來說,我們只對外提供的是一個 /healthcheck 檢查端點,引入HealthChecks.UI.dll 將會在前端生成友好的HealthReport 介面, 該庫支援後臺輪詢檢查、支援webhook 通知。
這裡就不展開說明,自行前往AspNetCore.Diagnostics.HealthChecks檢視相應文件,效果如下
至此,本文內容完畢:
使用ASP.NET Core框架實現一個稍複雜的HealthCheck端點 /healthz使用docker的HEALTHCHECK指令對接Web應用健康檢查端點