前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【5min+】保持程序健康的秘诀!AspNetCore的HealthCheck

【5min+】保持程序健康的秘诀!AspNetCore的HealthCheck

作者头像
句幽
发布2020-04-27 16:56:35
5410
发布2020-04-27 16:56:35
举报
文章被收录于专栏:一起玩转.NET一起玩转.NET

系列介绍

【五分钟的dotnet】是一个利用您的碎片化时间来学习和丰富.net知识的博文系列。它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net知识等等。 5min+不是超过5分钟的意思,"+"是知识的增加。so,它是让您花费5分钟以下的时间来提升您的知识储备量。

正文

在开发AspNet Core应用的时候,我们经常会为该应用公布一个特殊的检测接口出来。该接口的目的很简单,告诉某一些外界程序(比如docker,客户端等)这个程序现在是可以访问或者不能访问的,便于外界做出相应的操作,比如监控报警,页面通知用户稍作等待等。

在AspNet Core 2.2 之前,如果我们要实现一个这样的检测接口,需要建立一个单独的controller,比如HealthController。然后为其实现一个简单的检测方法:

[Route("working")]
public ActionResult Working()
{
    using (var connection = new SqlConnection(_connectionString))
    {
        try
        {
            connection.Open();
        }
        catch (SqlException)
        {
            return new HttpStatusCodeResult(503, "Generic error");
        }
    }

    return new EmptyResult();
}

该接口目的是检测应用与数据库的连接能否成功。如果成功连接,则返回状态码为200的空内容,如果失败则返回503。 外界程序可以通过定时访问 “\working” 路径,根据返回的对应Code来做出相应的反应。

运行状况检查

但是在Aspnet Core 2.2 之后,我们有了新的解决方式。只需要简单的操作就可以进行程序运行状况的检查。

x
x

我们只需要在Startup.cs中添加两句话就OK了:

public void ConfigureServices(IServiceCollection services)
{
    //使用该扩展方法
    services.AddHealthChecks();
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        //使用该扩展方法
        endpoints.MapHealthChecks("/health");
    });
}

默认情况是不需要在额外的引入其它nuget包的,因为AspNet Core自带了这些功能。

此时我们可以访问 "/health" 路径,将会看到对应结果:

x
x

如果程序正常,则返回Http状态码为200,显示内容为"Healthy"的结果。如果程序不正常,则返回Http状态码为503,显示内容为"UnHealthy"的结果。

这就是运行状况检查的初步使用。

为什么要自检?

看到这里,可能有些同学要问:“我引入一个检测到底有什么用?什么情况下我需要这么做呢?”

其实,对咱们的应用程序来说,做运行情况检查是非常有必要的。

就好比去医院看病的时候,医生往往会问病人:“你现在是感觉哪儿不舒服,对哪些药物过敏”等等问题。然后才能对症下药。

更形象的一个例子是做体检:人们一般会自费花钱定期去医院做体检,如果发现哪一检查项有异常的时候,就会报告给医院并且去寻找对应的医生,向医生说明情况之后得到对应的治疗方案。

所以咱们的应用程序也是一样的,“定期体检”有必要吗? 肯定是有必要的。如果不定期体检,我们很难知道现在程序运行状态到底是什么样子,或许它已经“濒临崩溃”了,需要立即释放内存。

还有一点就是:需要如实的报告检查情况。就如同医生问病人:“您哪不舒服?”,病人说:“我没病。我哪儿都没问题” 。 那医生只会认为病人是来搞笑的,所以放弃对他的治疗。

x
x

始终要相信一点,没有人比你自己更懂你自己。虽然外界的程序也会有各种其它方式来判断应用程序是否正常,但是它只能知道大概,只有程序体本身才能更清楚的知道现在运行的情况。

目的性的检查

最初我们只是简单的引入了 AddHealthChecks 。 但是它并没有任何特定的逻辑在里面。而现实场景我们是需要对各种指标进行检查的,就好比体检单上有多个体检项一样。所以我们需要实现自定义的检查功能。

比如咱们现在要实现一个对Sql Server 连接情况的检查。我们只需要实现 IHealthCheck 接口,实现CheckHealthAsync 方法就可以了:

public class SqlServerHealthCheck : IHealthCheck
{
    SqlConnection _connection;

    public string Name => "sql";

    public SqlServerHealthCheck(SqlConnection connection)
    {
        _connection = connection;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            _connection.Open();
        }
        catch (SqlException)
        {
            return Task.FromResult(HealthCheckResult.Unhealthy("From Sql Serve"));
        }

        return Task.FromResult(HealthCheckResult.Healthy());
    }
}

然后在Startup.csAddHealthChecks进行扩展:

services.AddHealthChecks()
        .AddCheck<SqlServerHealthCheck>("sql_check");

此时如果咱们再次访问"/health" 路径,就会发现应用会执行SqlServerHealthCheck里面的检查逻辑。

但是实际情况,咱们往往都会有许许多多的检查项,比如增加一个叫做MemoryHealthCheck的检查项:

public class MemoryHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        //doing some memory check things.
        return Task.FromResult(HealthCheckResult.Healthy());
    }
}

// startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
            .AddCheck<SqlServerHealthCheck>("sql_check")
            .AddCheck<MemoryHealthCheck>("memory_check");  // add this line
}

或许还有许许多多的检查项:FileSizeHealthCheckRedisHealthCheck等等。当我们将它们都添加上之后,则只有当所有的检查器都返回为Healthy的时候,才会认为是健康

但是某些情况我们又只想进行单项检查怎么办呢? 我们可以在 endpoints 的配置中新增另外的路由映射规则:

// startup.cs
 app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = s => s.Name.Equals("sql_check"),
        ResponseWriter = WriteResponse
    });

    endpoints.MapHealthChecks("/healthy", new HealthCheckOptions()
    {
        Predicate = s => s.Name.Equals("memory_check"),
        ResponseWriter = WriteResponse
    });
});

//指定返回格式
private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString());
}

我们在原有的基础上增加了HealthCheckOptions的参数,该参数指定了关于状态检测的匹配规则,返回状态码,返回格式等信息。

上面的代码我们指定了两个路由。当访问"health"路径的时候,则是对sql连接的检查(根据检查器名来匹配:Name.Equals("sql_check")),而访问"healthy"路径的时候,是对内存的检查。 最后还为他们指定了需要返回的内容(WriteResponse)。

接下来我们再次进行请求"health"路径,就会得到下面的结果:

x
x

自定义返回内容对咱们定位错误和记录日志十分有用。(就像看病的例子,病人更清晰的描述病情,医生就能够更容易定位病因。)。

第三方支持

虽然官方为我们提供的运行检查库已经足够轻量和简单。但是为了避免重复造轮子,我们可以使用AspNetCore.Diagnostics.HealthChecks包,该项目包含了许多情况的检查,比如 Sql ServerMySqlElasticsearchRedisKafka等等。

并且还为我们提供一个UI界面,可供查看。只需要在原有的基础上引入对应的代码就行了:

 public void ConfigureServices(IServiceCollection services)
{
    services.AddHealthChecks()
            .AddCheck<SqlServerHealthCheck>("sql_check")
            .AddCheck<MemoryHealthCheck>("memory_check");

    // add this line
    services.AddHealthChecksUI();
}

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = s => s.Name.Equals("sql_check"),
        ResponseWriter = WriteResponse
    });
    //add this line
    endpoints.MapHealthChecksUI();
});

当我们访问"/healthchecks-ui"路径时,就可以看到这样的UI:

x
x

默认是没有任何的检测配置项的,如果咱们需要可视化运行状态,需要在AddHealthChecksUI中进行配置:

services.AddHealthChecksUI(setupSettings: setup =>
{
    setup.AddHealthCheckEndpoint("endpoint1", "http://localhost:5001/health");
});

再次查看UI界面,就能看到对应的检查项:

x
x

总结

本篇文章主要为大家介绍了 aspnet core 2.2之后所推出的“HealthCheck”,与使用传统的Controller 公开API进行检查不同,使用“IHealthCheck”能够更快速的进行访问(毕竟不需要进行模型绑定等操作),而且IHealthCheck接口能够更好的进行检查项扩展。让我们能够更快更清楚的了解到应用程序运行的情况。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 系列介绍
  • 正文
    • 运行状况检查
      • 为什么要自检?
        • 目的性的检查
          • 第三方支持
          • 总结
          相关产品与服务
          云数据库 Redis
          腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档