Docker-HealthCheck指令探測ASP.NET Core容器健康狀態

寫在前面

HealthCheck 不僅是對應用程序內運行情況、數據流通情況進行檢查,還包括應用程序對外部服務或依賴資源的健康檢查。

健康檢查通常是以<code>暴露應用程序的HTTP端點/<code>的形式實施,可用於配置健康探測的的場景有 :

  1. 容器或負載均衡器 探測應用狀態,執行既定策略,例如:容器探測到應用unhealthy可終止後續的滾動部署或者重啟容器;負載均衡器探測到實例unhealthy能將請求路由到健康的運行實例。

  2. 對應用程序種依賴的第三方服務進行健康探測,比如redis、database、外部服務接口

  3. 內存、硬盤、網絡等物理依賴資源的探測

HealthCheck提供對外暴露程序運行狀態的機制。

容器HEALTHCHECK指令

一般情況下我們很容易知道容器<code>正在運行running/<code>, 但容器作為相對獨立的應用執行環境,有時候並不知道容器是否<code>以預期方式正確運作working/<code>

Dockerfile HEALTHCHECK指令提供了探測容器以預期工作的輪詢機制,輪詢內容可由應用自身決定。

具體而言:通過在容器內運行shell命令來探測容器健康狀態,以Shell命令的退出碼錶示容器健康狀態:

0 指示容器健康

1 指示容器不健康

2 指示不使用這個退出碼

<code>// 可定義輪詢interval、探測超時timeout、 重試retries參數輪詢探測
HEALTHCHECK [OPTIONS] CMD command
/<code>

Every Linux or Unix command executed by the shell>

對Web應用,自然會聯想到使用<code>curl命令訪問端點/<code>去探測容器應用:

<code>curl web端點成功,命令返回0(真);curl web端點失敗,命令返回非0(假)/<code>

<code>// curl -f 表示請求失敗返靜默輸出
HEALTHCHECK --interval=5m --timeout=3s --retries=3 CMD curl -f http://localhost:5000/healthz || exit 1
/<code>

探測命令在stdout或stderr輸出的任何內容會在容器Health Status中存儲,可通過docker inspect [ContainerId] 查看HealthCheck狀態。

下面漸進式演示使用Docker平臺的HEALTHCHECK指令對接 ASP.NET Core程序的健康檢查能力。

Docker-HealthCheck指令探测ASP.NET Core容器健康状态

ASP.NET Core實現HealthCheck端點

ASPNET Core在2.2版本內置了健康檢查的能力:終端中間件(滿足該路徑的url請求,將會被該中間件處理)。

<code>public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks;
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/healthcheck");
}
/<code>

Asp.NetCore 3.1將健康檢查集成在 EndPoints,請自行修改。

請求/healthcheck端點, 程序會進行健康檢查邏輯並響應輸出, 默認的行為:

① <code>對healthy、degraded狀態返回200 OK響應碼;對於unhealthy返回503 Service Unavailable響應碼/<code>

② 響應體只會包含簡單的HealthStatus枚舉字符串

③ 將每次健康檢查的結果寫入HealthReport對象。

作為企業級項目,存在對Web項目物理資源和服務依賴的健康檢查需求, 這裡我們為避免重複造輪子,引入了開源的力量。

開源社區對HealthCheck的支持

開源的企業級AspNetCore.Diagnostics.HealthChecks系列組件,該系列組件支持多種物理資源和服務依賴的健康檢查,支持報告推送,支持友好的檢查報告UI(支持後臺輪詢檢查)、支持webhook通知。

下面的步驟演示了對web程序HTTP請求、Redis、Sqlite等服務進行健康檢查的端點配置

① 引入AspNetCore.HealthChecks.Redis 、 AspNetCore.HealthChecks.Sqlite nuget庫

② Startup.cs配置並啟用健康檢查

<code>// 以下代碼截取自 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枚舉值
/<code>

再次強調,容器HealthCheck指令不關注Shell命令的執行過程,<code>只關注shell命令的執行結果/<code>

<code>// docker-compose.yml文件健康檢查 參考如下配置:
healthcheck:
test: curl -f http://localhost/healthcheck || exit 1
interval: 1m30s
timeout: 10s
retries: 3
/<code>

HealthChecks-UI 瞭解一下

拋開Docker的HEALTHCHECK指令、負載均衡器的輪詢機制不談,我們的Web自身也可以進行 輪詢健康檢查並給出告警。

就我們上面的Web 實例來說,我們只對外提供的是一個 /healthcheck 檢查端點,引入HealthChecks.UI.dll 將會在前端生成友好的HealthReport 界面, 該庫支持後臺輪詢檢查、支持webhook 通知。

這裡就不展開說明,自行前往AspNetCore.Diagnostics.HealthChecks查看相應文檔,效果如下

Docker-HealthCheck指令探测ASP.NET Core容器健康状态

至此,本文內容完畢:

  • 使用ASP.NET Core框架實現一個稍複雜的HealthCheck端點 /healthz

  • 使用docker的HEALTHCHECK指令對接Web應用健康檢查端點

Docker-HealthCheck指令探测ASP.NET Core容器健康状态


分享到:


相關文章: