博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET Core 3.0之深入源码理解HealthCheck(一)
阅读量:4032 次
发布时间:2019-05-24

本文共 5594 字,大约阅读时间需要 18 分钟。

写在前面

我们的系统可能因为正在部署、服务异常终止或者其他问题导致系统处于非健康状态,这个时候我们需要知道系统的健康状况,而健康检查可以帮助我们快速确定系统是否处于正常状态。一般情况下,我们会提供公开的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
CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default);}

HealthCheckRegistration

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

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

  • 标识健康检查名称

  • 创建IHealthCheck实例

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

  • 失败状态标识

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

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

public Func
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
Tags { get; }

HealthCheckResult

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

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

  • 组件的当前状态

  • 异常信息

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

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

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

public struct HealthCheckResult{
private static readonly IReadOnlyDictionary
_emptyReadOnlyDictionary = new Dictionary
(); public HealthCheckResult(HealthStatus status, string description = null, Exception exception = null, IReadOnlyDictionary
data = null) {
Status = status; Description = description; Exception = exception; Data = data ?? _emptyReadOnlyDictionary;} public IReadOnlyDictionary
Data { get; } public string Description { get; } public Exception Exception { get; } public HealthStatus Status { get; } public static HealthCheckResult Healthy(string description = null, IReadOnlyDictionary
data = null){
return new HealthCheckResult(status: HealthStatus.Healthy, description, exception: null, data);} public static HealthCheckResult Degraded(string description = null, Exception exception = null, IReadOnlyDictionary
data = null){ return new HealthCheckResult(status: HealthStatus.Degraded, description, exception: exception, data);} public static HealthCheckResult Unhealthy(string description = null, Exception exception = null, IReadOnlyDictionary
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
entries, TimeSpan totalDuration) {
Entries = entries; Status = CalculateAggregateStatus(entries.Values); TotalDuration = totalDuration; } public IReadOnlyDictionary
Entries { get; } public HealthStatus Status { get; } public TimeSpan TotalDuration { get; } private HealthStatus CalculateAggregateStatus(IEnumerable
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; }}

总结

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

转载地址:http://zsgbi.baihongyu.com/

你可能感兴趣的文章
[互联网学习]如何提高网站的GooglePR值
查看>>
[关注大学生]求职不可不知——怎样的大学生不受欢迎
查看>>
[关注大学生]读“贫困大学生的自白”
查看>>
[互联网关注]李开复教大学生回答如何学好编程
查看>>
[关注大学生]李开复给中国计算机系大学生的7点建议
查看>>
[关注大学生]大学毕业生择业:是当"鸡头"还是"凤尾"?
查看>>
[茶余饭后]10大毕业生必听得歌曲
查看>>
gdb调试命令的三种调试方式和简单命令介绍
查看>>
C++程序员的几种境界
查看>>
VC++ MFC SQL ADO数据库访问技术使用的基本步骤及方法
查看>>
VUE-Vue.js之$refs,父组件访问、修改子组件中 的数据
查看>>
Vue-子组件改变父级组件的信息
查看>>
Python自动化之pytest常用插件
查看>>
Python自动化之pytest框架使用详解
查看>>
【正则表达式】以个人的理解帮助大家认识正则表达式
查看>>
性能调优之iostat命令详解
查看>>
性能调优之iftop命令详解
查看>>
非关系型数据库(nosql)介绍
查看>>
移动端自动化测试-Windows-Android-Appium环境搭建
查看>>
Xpath使用方法
查看>>