写在前面

我们的系统可能因为正在部署、服务异常终止或者其他问题导致系统处于非健康状态,这个时候我们需要知道系统的健康状况,而健康检查可以帮助我们快速确定系统是否处于正常状态。一般情况下,我们会提供公开的HTTP接口,用于专门化健康检查。

NET Core提供的健康检查库包括Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions和Microsoft.Extensions.Diagnostics.HealthChecks。这两个库共同为我们提供了最基础的健康检查的解决方案,后面扩展的组件主要有下面几个,本文不作其他说明。

AspNetCore.HealthChecks.System
AspNetCore.HealthChecks.Network
AspNetCore.HealthChecks.SqlServer
AspNetCore.HealthChecks.MongoDb
AspNetCore.HealthChecks.Npgsql
AspNetCore.HealthChecks.Redis
AspNetCore.HealthChecks.AzureStorage
AspNetCore.HealthChecks.AzureServiceBus
AspNetCore.HealthChecks.MySql
AspNetCore.HealthChecks.DocumentDb
AspNetCore.HealthChecks.SqLite
AspNetCore.HealthChecks.Kafka
AspNetCore.HealthChecks.RabbitMQ
AspNetCore.HealthChecks.IdSvr
AspNetCore.HealthChecks.DynamoDB
AspNetCore.HealthChecks.Oracle
AspNetCore.HealthChecks.Uris

源码探究

Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions是.NET Core健康检查的抽象基础,从中我们可以看出这个库的设计意图。它提供了一个统一的接口IHealthCheck,用于检查应用程序中各个被监控组件的状态,包括后台服务、数据库等。这个接口只有一个方法CheckHealthAsync,

该方法有一个参数是HealthCheckContext,它表示当前健康检查执行时所关联的上下文对象,它的返回值HealthCheckResult表示当前健康检查结束后所产生的被监控组件的运行状态。

源码如下所示:

public interface IHealthCheck{    Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default);}

HealthCheckRegistration

HealthCheckContext里面只有一个成员就是HealthCheckRegistration实例。

HealthCheckRegistration是一个相当重要的对象,它体现了健康检查需要关注和注意的地方,其内部涉及到五个属性,分别用于:

  • 标识健康检查名称

  • 创建IHealthCheck实例

  • 健康检查的超时时间(防止我们因为健康检查而过多占用资源)

  • 失败状态标识

  • 一个标签集合(可用于健康检查过滤)

这五个属性的相关源码如下:

public Func<IServiceProvider, IHealthCheck> Factory{    get => _factory;    set    {        if (value == null)        {            throw new ArgumentNullException(nameof(value));        }            _factory = value;    }}    public HealthStatus FailureStatus { get; set; }    public TimeSpan Timeout{    get => _timeout;    set    {        if (value <= TimeSpan.Zero && value != System.Threading.Timeout.InfiniteTimeSpan)        {            throw new ArgumentOutOfRangeException(nameof(value));        }            _timeout = value;    }}    public string Name{    get => _name;    set    {        if (value == null)        {            throw new ArgumentNullException(nameof(value));        }            _name = value;    }}    public ISet<string> Tags { get; }

HealthCheckResult

HealthCheckResult是一个结构体,可以看出这里更多的是基于承担数据存储和性能问题的考量。

HealthCheckResult用于表示健康检查的相关结果信息,同样的,通过该类,我们知道了健康检查需要关注的几个点:

  • 组件的当前状态

  • 异常信息

  • 友好的描述信息(不管是异常还是正常)

  • 额外可描述当前组件的键值对,这是一个开放式的属性,方面我们记录更多信息

该类含有四个公共属性,和三个方法,相关源码如下:

public struct HealthCheckResult{    private static readonly IReadOnlyDictionary<string, object> _emptyReadOnlyDictionary = new Dictionary<string, object>();    public HealthCheckResult(HealthStatus status, string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)    {        Status = status;        Description = description;        Exception = exception;    Data = data ?? _emptyReadOnlyDictionary;}public IReadOnlyDictionary<string, object> Data { get; }public string Description { get; }public Exception Exception { get; }public HealthStatus Status { get; }public static HealthCheckResult Healthy(string description = null, IReadOnlyDictionary<string, object> data = null){    return new HealthCheckResult(status: HealthStatus.Healthy, description, exception: null, data);}public static HealthCheckResult Degraded(string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null){    return new HealthCheckResult(status: HealthStatus.Degraded, description, exception: exception, data);}public static HealthCheckResult Unhealthy(string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null){    return new HealthCheckResult(status: HealthStatus.Unhealthy, description, exception, data);}}

可以看出这个三个方法都是基于HealthStatus这个枚举而创建不同状态的HealthCheckResult实例,这个枚举表达了健康检查需要关注的几种状态,健康、异常以及降级。

HealthStatus的源码如下:

public enum HealthStatus{    Unhealthy = 0,     Degraded = 1,     Healthy = 2,}

IHealthCheckPublisher

健康检查功能本质上是一种轮询功能,需要定期执行,.NET Core 抽象定期执行的接口,即IHealthCheckPublisher,我们可以通过实现这个接口,并与我们自定义的定时功能相结合。

同时,作为一次健康检查,我们还需要关注相关的健康检查报告,那么我们需要关注那些点呢?

  • 额外可描述当前组件的键值对,这是一个开放式的属性,方面我们记录更多信息

  • 友好的描述信息(不管是异常还是正常)

  • 组件的当前状态

  • 异常信息

  • 当前这次检查所耗费的时间

  • 相关的标签信息

HealthReportEntry表示单个健康检查报告,HealthReport表示一组健康检查报告。HealthReport内部维护了一个HealthReportEntry的字典数据,HealthReport源码如下所示:

public sealed class HealthReport{    public HealthReport(IReadOnlyDictionary<string, HealthReportEntry> entries, TimeSpan totalDuration)    {        Entries = entries;        Status = CalculateAggregateStatus(entries.Values);        TotalDuration = totalDuration;    }    public IReadOnlyDictionary<string, HealthReportEntry> Entries { get; }    public HealthStatus Status { get; }    public TimeSpan TotalDuration { get; }    private HealthStatus CalculateAggregateStatus(IEnumerable<HealthReportEntry> entries)    {        var currentValue = HealthStatus.Healthy;        foreach (var entry in entries)        {            if (currentValue > entry.Status)            {                currentValue = entry.Status;            }            if (currentValue == HealthStatus.Unhealthy)            {                // Game over, man! Game over!                // (We hit the worst possible status, so there's no need to keep iterating)                return currentValue;            }        }        return currentValue;    }}

总结

通过以上内容,我们知道了,一个完整的健康检查需要关注健康检查上下文、健康状态的维护、健康检查结果、健康检查报告,同时,为了更好的维护健康检查,我们可以将健康检查发布抽象出来,并与外部的定时器相结合,共同守护健康检查程序。

.NET Core 3.0之深入源码理解HealthCheck(一)相关推荐

  1. .NET Core 3.0之深入源码理解Startup的注册及运行

    开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程序的起点.通过使用Startup,可以配置化处理所有向应用程序所做的请求的管道,同时也可 ...

  2. .NET Core 3.0之深入源码理解ObjectPool(一)

    写在前面 对象池是一种比较常用的提高系统性能的软件设计模式,它维护了一系列相关对象列表的容器对象,这些对象可以随时重复使用,对象池节省了频繁创建对象的开销. 它使用取用/归还的操作模式,并重复执行这些 ...

  3. .NET Core 3.0之深入源码理解Host(二)

    写在前面 停了近一个月的技术博客,随着正式脱离996的魔窟,接下来也正式恢复了.本文从源码角度进一步讨论.NET Core 3.0 中关于Host扩展的一些技术点,主要内容是关于创建Long Run ...

  4. .NET Core 3.0之深入源码理解Kestrel的集成与应用(二)

    前言 前一篇文章主要介绍了.NET Core继承Kestrel的目的.运行方式以及相关的使用,接下来将进一步从源码角度探讨.NET Core 3.0中关于Kestrel的其他内容,该部分内容,我们无需 ...

  5. .NET Core 3.0之深入源码理解Kestrel的集成与应用(一)

    写在前面 ASP.NET Core 的 Web 服务器默认采用Kestrel,这是一个基于libuv(一个跨平台的基于Node.js的异步I/O库)的跨平台.轻量级的Web服务器. 在开始之前,先回顾 ...

  6. .NET Core 3.0之深入源码理解Configuration(一)

    微软在.NET Core里设计出了全新的配置体系,并以非常灵活.可扩展的方式实现.从其源码来看,其运行机制大致是,根据其Source,创建一个Builder实例,并会向其添加Provider,在我们使 ...

  7. .NET Core 3.0之深入源码理解ObjectPool(二)

    写在前面 前文主要介绍了ObjectPool的一些理论基础,本文主要从源码角度理解Microsoft.Extensions.ObjectPool是如何实现的.下图为其三大核心组件图: 核心组件 Obj ...

  8. .NET Core 3.0之深入源码理解HttpClientFactory(二)

    写在前面 上一篇文章讨论了通过在ConfigureServices中调用services.AddHttpClient()方法,并基于此进一步探讨了DefaultHttpClientFactory是如何 ...

  9. .NET Core 3.1之深入源码理解HealthCheck(二)

    写在前面 前文讨论了HealthCheck的理论部分,本文将讨论有关HealthCheck的应用内容. 可以监视内存.磁盘和其他物理服务器资源的使用情况来了解是否处于正常状态. 运行状况检查可以测试应 ...

最新文章

  1. linux每日命令(15):tail命令
  2. 【正则表达式】1.入门
  3. 是是非非本寻常,我们要不要跳槽。
  4. 算法试题 - 找出字符流中第一个不重复的元素
  5. C# Excel处理工具
  6. Linux 用户线程数与文件句柄树调整(nproc与nofile的问题)
  7. AndroidVector初探
  8. python从入门到精通pdf清华大学出版社-python从入门到精通 清华大学出版社
  9. 解决OptiSystem安装、使用过程中遇到的问题
  10. jclasslib插件_IDEA安装jclasslib 插件查看字节码详解
  11. Linux dos攻击服务器,Linux服务器如何防止DoS攻击
  12. 毕业设计-电子商务网站(二)
  13. TestNG单元测试框架详解
  14. Jetson Nano交叉编译教程
  15. python串口控制8通道继电器方法笔记
  16. 微信群舆情怎么监测?
  17. 计算机专业要学英语口语,学习英语口语必须掌握两大法宝
  18. win7系统如何关闭安全模式,关闭安全模式的方法
  19. 「react进阶」一文吃透React高阶组件(HOC)
  20. 聚类算法——python实现SOM算法

热门文章

  1. Ubuntu 下配置 NFS
  2. 关于iPhone的UIView刷新(转)
  3. zoj2271 Chance to Encounter a Girl(DP)
  4. 注册表被黑客篡改 怎样修复_使用快速注册表黑客设置Office 2007配色方案
  5. vlc传输_如何使用VLC通过网络流式传输视频和音乐
  6. 移动硬盘改台式机硬盘_如何在台式机或移动设备上离线使用Google云端硬盘
  7. 前端工程化:围绕Jenkins打造工作流的过程
  8. css sprite讲解与使用实例
  9. SSIS package 更新 variable
  10. Application Fundamentals