.Net Core实现健康检查

  • 2019 年 11 月 3 日
  • 笔记

ASP.NET Core 提供运行状况检查中间件和库,以用于报告应用基础结构组件的运行状况。
运行状况检查由应用程序作为 HTTP 终结点公开。 可以为各种实时监视方案配置运行状况检查终结点:

  • 运行状况探测可以由容器业务流程协调程和负载均衡器用于检查应用的状态。 例如,容器业务流程协调程序可以通过停止滚动部署或重新启动容器来响应失败的运行状况检查。 负载均衡器可以通过将流量从失败的实例路由到正常实例,来应对不正常的应用。
  • 可以监视内存、磁盘和其他物理服务器资源的使用情况来了解是否处于正常状态。
  • 运行状况检查可以测试应用的依赖项(如数据库和外部服务终结点)以确认是否可用和正常工作。

这个示例展示数据库的运行状态,他在其验证数据库连接并返回相应的结果

        [Route("health")]          public ActionResult Health()          {              using (var connection = new SqlConnection("Server=.;Initial Catalog=master;Integrated Security=true"))              {                  try                  {                      connection.Open();                  }                  catch (SqlException)                  {                      return new StatusCodeResult(503);                    }              }                return new EmptyResult();          }  

当我们请求该地址的时候时,如果连接到数据库时出现任何连接问题,它将显示一条包含200状态代码和503状态代码的空消息​​。

image

image

现在基于这些结果状态码,我们可以监视系统采取相关的操作。

从.NET Core2.2开始,我们不需要为运行状态在去自定义检查控制器和接口,而是框架本身已经为我们提供了运行状况的检查服务。

安装和运行

Install-Package Microsoft.Extensions.Diagnostics.HealthChecks

安装后,我们需要在Startup.cs文件的ConfigureServices()和Configure()方法中添加。

        public void ConfigureServices(IServiceCollection services)          {              services.AddHealthChecks();          }          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)          {              app                  .UseHealthChecks("/health");            }    

我们在configure()方法中配置完端点后,我们就可以通过 /health来请求查看我们的应用程序的健康程度的。

image

但是这样对于我们刚才的需求是满足不了的,那么我们如何自定义我们的健康度检查呢?

两种方式来处理

option 1

        public void ConfigureServices(IServiceCollection services)          {              services.AddHealthChecks()    .AddCheck("sql", () =>    {          using (var connection = new SqlConnection("Server=.;Initial Catalog=master;Integrated Security=true"))        {            try            {                connection.Open();            }            catch (SqlException)            {                return HealthCheckResult.Unhealthy();            }        }          return HealthCheckResult.Healthy();      });          }  

在这里我们使用匿名方法AddCheck(),来编写我们的自定义的验证逻辑,结果是HealthCheckResult对象,该对象包含3个选项

  1. Healthy 健康
  2. Unhealthy 不良
  3. Degraded 降级

option 2

实现IHealthCheck接口并实现CheckHealthAsync()方法,如下所示:

   public class DatabaseHealthCheck : IHealthCheck          {              public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken =               default)              {                  using (var connection = new SqlConnection("Server=.;Initial Catalog=master;Integrated Security=true"))                  {                      try                      {                          connection.Open();                      }                      catch (SqlException)                      {                          return  Task.FromResult(HealthCheckResult.Unhealthy());                      }                  }                    return Task.FromResult(HealthCheckResult.Healthy());                }          }

创建该类之后,我们需要通过使用一些有效的唯一名称,AddCheck ()方法在ConfigureServices()方法中提及该类,如下所示。

     public void ConfigureServices(IServiceCollection services)          {              services.AddHealthChecks()            .AddCheck<DatabaseHealthCheck>("sql");          }

现在我们的代码就写完了,我们可以像上面那样添加任意数量的Health Task,它将按照我们在此处声明的顺序运行。

自定义状态码

在之前我们也说过200为健康,503为不健康那么Healthcheck服务甚至通过以下方式使用其options对象提供自定义状态代码,为我们提供了更改此默认的状态码。

config.MapHealthChecks("/health", new HealthCheckOptions                       {                          ResultStatusCodes = new Dictionary<HealthStatus, int> { { HealthStatus.Unhealthy, 420 }, { HealthStatus.Healthy, 200 }, { HealthStatus.Degraded, 419 } }                           }); 

自定义输出

我们可以自定义输出,以获取有关每个运行状况检查任务的更清晰详细的信息。如果我们有多个运行状况检查任务来分析哪个任务使整个服务健康状态变为”不正常“,这将非常有用。

我们可以通过HealthCheckOptions ResponseWriter属性来实现。

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)          {              app                   .UseRouting()                   .UseEndpoints(config =>                   {                       config.MapHealthChecks("/health", new HealthCheckOptions                       {                          ResponseWriter=CustomResponseWriter                         });                     });            }          private static Task CustomResponseWriter(HttpContext context, HealthReport healthReport)          {              context.Response.ContentType = "application/json";                var result = JsonConvert.SerializeObject(new              {                  status = healthReport.Status.ToString(),                  errors = healthReport.Entries.Select(e => new                  {                      key = e.Key,                      value = e.Value.Status.ToString()                  })              });              return context.Response.WriteAsync(result);            }

image

现在以json显示我们的详细信息,完成了健康状态的检查.

健康检查界面

Install-Package AspNetCore.HealthChecks.UI

安装完成后,需要相应地在ConfigureServices()和Configure()方法中调用相应的服务方法。

public void ConfigureServices(IServiceCollection services)  {      services.AddHealthChecksUI();  }    public void Configure(IApplicationBuilder app, IHostingEnvironment env)  {      app.UseHealthChecksUI();  }  

配置完成后,您可以运行应用程序并指向/ healthchecks-ui地址,该端点显示如下的UI.

image

但是界面上没有我们刚才自定义的,那我们在进行配置

Appsetting.json

{    "ApplicationInsights": {      "InstrumentationKey": "your-instrumentation-key"    },    "Logging": {      "LogLevel": {        "Default": "Warning"      }    },    "AllowedHosts": "*",    "HealthChecksUI": {      "HealthChecks": [        {          "Name": "Test Health",          "Uri": "https://localhost:44342/health"        }      ],      "EvaluationTimeinSeconds": 10,      "MinimumSecondsBetweenFailureNotifications": 60    }  }  

image

这样就可以看到健康状态了