系列导航及源代码
需求
应用健康检查在容器部署的微服务场景下非常常见,相比而言单体非容器部署的应用就不太关心这个特性,为了后续的内容我们在本文中简单介绍一下如何实现应用程序的健康检查功能。
目标
实现TodoList
的健康检查功能。
原理与思路
.NET框架从.NET Core 2.2版本开始引入了相关的功能,同时AspNetCore.Diagnostics.HealthChecks包提供了更为丰富的健康检查功能,包括数据库,消息总线,Redis和ElasticSearch的健康检查。
健康检查探针(probe)分为三种:
- readiness probes:应用程序就绪探针,判断当前应用程序是否已经启动。
- liveness probes: 应用程序存活探针,判断当前应用程序是否出于活动状态。
- startup probes:应用程序功能探针,一般我们用
hc
来表示其端口,可以用来判断应用程序内部功能是否正常(比如判断数据库连接是否正常,判断Redis连接是否正常之类)。
在本文中我们不过多地发散,通过创建一个自定义的健康检查对象来实现。
实现
自定义健康检查,实现IHealthCheck接口
Microsoft.Extensions.Diagnostics.HealthChecks
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace TodoList.Application.Common;
public class ApplicationHealthCheck : IHealthCheck
{
private static readonly Random _rnd = new ();
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var result = _rnd.Next(5) == 0
? HealthCheckResult.Healthy()
: HealthCheckResult.Unhealthy("Failed random");
return Task.FromResult(result);
}
}
添加服务和中间件
首先在Application/DependencyInjection
中添加健康检查服务:
DependencyInjection.cs
services.AddHealthChecks().AddCheck<ApplicationHealthCheck>("Random Health Check");
然后修改Program
中间件配置如下:
Program.cs
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpLogging();
app.MapDefaultControllerRoute();
app.MapHealthChecks("/liveness");
app.MapHealthChecks("/ready");
app.MapHealthChecks("/hc");
验证
启动Api
项目,执行健康检查的三个GET
接口,截图我只贴其中一个,因为我们在实现健康检查的时候,采用了随机数返回Healthy
或者Unhealthy
的方式,所以多请求几次,应该能看到下面的响应:
一点扩展
关于Smart probes和Dumb probes
- 所谓
Smart probes
最典型的目的就是为了验证应用程序是否能正确工作,像一开始所说的,它可以用来探测外部依赖如数据库、消息队列、甚至是其他API的连接是否正常,程序在这些地方是否可以按预期工作。 - 相对而言,
Dumb probes
典型的应用目的是用来判断应用程序没有崩溃,它并不检查功能及依赖上的正确性,通常表现为HTTP的直接响应。
推荐的使用方式是:
- 对于
liveness
检查,使用dumb probes
就可以了,因为只要能够响应HTTP请求,就可以证明应用程序没有崩溃。 - 对于
startup
或者称作真正的“健康”检查hc
,使用smart probes
,因为这时候不仅要保证程序没有崩溃,我们还需要某种程度的功能及依赖的健康检查,以证明程序能够按预期工作。 - 对于
readiness
检查,需要根据实际的需求来看,如果我们没有定义特殊的应用程序“就绪”标准,使用dumb probes
就可以;反之如果我们需要进行某种程度的逻辑检查来定义“就绪”,那么就需要使用smart probes
。
设置Dumb健康检查接口
修改中间件配置:
Program.cs
app.MapHealthChecks("/liveness", new HealthCheckOptions { Predicate = r => r.Name.Contains("self") });
app.MapHealthChecks("/ready", new HealthCheckOptions { Predicate = _ => false });
这时候我们再去请求健康检查,这两个接口已经固定返回Healthy
结果了,hc接口依然按照我们之前设置的进行随机返回。
总结
本文我们简单地实现了健康检查接口,目前还不太能看得出来作用,但是当我们进行容器化部署,或是进行k8s部署时,健康检查探针的作用就比较明显了。关于健康检查,更多用法请参考官方文档:Health checks in ASP.NET Core