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容器健康状态


分享到:


相關文章: