当客户由于技术问题无法使用生产运行的应用程序时,我们不仅在赔钱,而且还信任客户对我们产品的信任。事实上,他们可能会在社交媒体、朋友或商店评论上散布关于我们产品的坏话,或者——甚至更糟——转移到竞争对手那里。
基本上,当利益相关者无法使用应用程序时,它就不存在。
当然可能会发生。这可能是因为人为错误、错误配置或错误。或者可能是因为我们的云提供商有一些问题。
由于这些原因,我们必须立即知道应用程序何时下线。
最常用和最简单的技术之一是健康检查端点。
健康检查端点,是由应用程序公开的 API,除了回复一个肯定的状态码之外没有任何逻辑;如果呼叫者没有收到任何响应或状态码不是预期的,则表示存在错误,必须使用您选择的技术(电子邮件、推送通知..短信等)发送警报。
当然,Asp.Net Core 提供了内置机制来实现健康检查端点。
实现一个简单的健康检查端点
创建一个 Asp.Net Core 项目。对于这个演示(您可以在本文末尾找到源代码),我将使用 dotnet 6 和新的最小主机启动模板。
安装 NuGet 包Microsoft.Extensions.Diagnostics.HealthChecks
并对其进行配置:
var builder = WebApplication . CreateBuilder ( args ); builder . Services . AddHealthChecks (); var app = builder . Build (); app . MapHealthChecks ( "/alive" ); app . Run ();
运行应用程序并导航到localhost:<port>/alive
,您应该会看到如下内容:
如果您尝试使用 Postman 或类似工具调用相同的端点,您会看到状态码为200 OK
。
万岁,健康检查端点已准备好定期消费!
高级场景
这可能是应用程序在线但由于某种原因无法与数据库通信的情况。这可能会对我们的客户造成很大的伤害,并且用户可能无法执行几乎所有的操作。最好立即得到通知。
实体框架健康检查
此外,Entity Framework 提供了一种内置机制来监视应用程序和 SQL 实例数据库之间的连接。
注意:要继续,当然您必须配置实体框架并指向正在运行的 SQL 数据库
从 NuGet 安装包Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
并配置它:
services. AddHealthChecks() .AddDbContextCheck<MyDbContext>("/dbcontext");
运行应用程序并再次指向localhost:<port>/alive
你应该得到相同的结果:
默认情况下,它会在后台检查:
DbContextHealthCheck 调用 EF Core 的 CanConnectAsync 方法。您可以自定义使用 AddDbContextCheck 方法重载检查运行状况时运行的操作。
健康检查的名称是 TContext 类型的名称。
它现在可以工作了,但仍然存在一个问题:无论我们点击哪个健康检查端点( /alive
或/dbcontext
),都会执行两个检查,因此暴露两个不同的 API 是没有用的。
如何为不同的检查设置不同的端点?答案是,通过检查姓名。
更改端点注册如下:
const string ALIVE = "alive"; const string ALIVE_DBCONTEXT = "dbcontext"; ... builder.Services.AddHealthChecks().AddDbContextCheck<MyDbContext>(name: ALIVE_DBCONTEXT); app.MapHealthChecks( "/alive", new HealthCheckOptions { Predicate = (c) => c.Name == ALIVE }); app.MapHealthChecks( "/dbcontext", new HealthCheckOptions { Predicate = (c) => c.Name == ALIVE_DBCONTEXT });
在这种情况下,我们为特定的健康检查端点命名。当名称匹配时,执行健康检查。
为了得到确认,我们可以做一个测试:
- 在本地 Docker 容器中运行应用程序和数据库
- 导航到
localhost:<port>/alive
:你应该得到Healthy
结果 - 停止数据库容器并刷新页面:你仍然应该得到
Healthy
的结果 - 导航到
localhost:<port>/dbcontext
:你应该得到Unhealthy
结果 - 重新启动数据库容器并刷新页面:你应该得到
Healthy
的结果
自定义检查:Azure Cosmos DB
Asp.Net 允许在执行健康检查时定义一些自定义代码。在这种情况下,我们可以测试与 Azure Cosmos DB 实例的连接,因为 .NET SDK 不提供任何机制来检查应用程序和数据库服务之间的连接。
以下示例使用container.ReadContainerAsync()
测试连接,该方法需要执行数据库访问权限。
// Cosmos initialization builder . Services . AddHealthChecks () . AddDbContextCheck < MyDbContext >( name : ALIVE_DBCONTEXT ) . AddCheck < CosmosHealthChecker >( name : ALIVE_COSMOS ); ... app . MapHealthChecks ( "/cosmos" , new HealthCheckOptions { Predicate = ( c ) => c . Name == ALIVE_COSMOS }); public class CosmosHealthChecker : IHealthCheck { private readonly IServiceScopeFactory _serviceScopeFactory ; private readonly IConfiguration _configuration ; private readonly ILogger < CosmosHealthChecker > _logger ; public CosmosHealthChecker ( IServiceScopeFactory scopeFactory , IConfiguration configuration , ILogger < CosmosHealthChecker > logger ) { _serviceScopeFactory = scopeFactory ; _configuration = configuration ; _logger = logger ; } public async Task < HealthCheckResult > CheckHealthAsync ( HealthCheckContext context , CancellationToken cancellationToken = default ) { try { string collectionName = _configuration [ "Cosmos:Collection" ]; using IServiceScope scope = _serviceScopeFactory . CreateScope (); Database db = scope . ServiceProvider . GetRequiredService < Database >(); Container container = db . GetContainer ( collectionName ); await container . ReadContainerAsync ( cancellationToken : cancellationToken ); return new HealthCheckResult ( HealthStatus . Healthy ); } catch ( Exception ex ) { _logger . LogError ( ex , "Error pinging Cosmos db" ); return new HealthCheckResult ( context . Registration . FailureStatus , "An unhealthy result." ); } } }
结论
我们明白,当用户无法访问我们的服务时通知我们的警报系统有多么重要,我们需要为此付出努力。
这篇文章解释了我们如何在 Asp.Net 项目中提供一些健康检查端点,只需几行代码?
与往常一样,源代码可在我的GitHub 个人资料中找到。
布鲁诺·纳西门托 ( Bruno Nascimento ) 在Unsplash上拍摄的照片
原文: https://dev.to/krusty93/implementing-health-checks-pt1-aspnet-core-6-configuration-6gp