.NET Core-depth understanding of the source 3.0 HealthCheck (a)

EDITORIAL

Probably because our system is being deployed, service or other problems cause abnormal termination system is in a healthy state, this time we need to know the health system, and health check can help us to quickly determine whether the system is in a normal state. Under normal circumstances, we will provide open HTTP interface for specialized health checks.

NET Core provides health screening library includes Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions and Microsoft.Extensions.Diagnostics.HealthChecks. The two libraries together provide a health check of the most basic solutions to our extended behind the main components are the following, we will not be otherwise.

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

Source Exploration

Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions is the abstraction of the underlying .NET Core health check, which we can see the design intent of this library. It provides a unified interface IHealthCheck, for each state to be monitored component inspection applications, including back-office services, databases, and so on. This interface is only one way CheckHealthAsync,

This method has one parameter is HealthCheckContext, which indicates the current context object associated with the health check when executed, its return value indicates HealthCheckResult monitored operating state after the current component generated by the health examination.

Source as follows:

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

HealthCheckRegistration

HealthCheckContext there is only one member is HealthCheckRegistration instance.

And HealthCheckRegistration is a very important subject, which reflects the need to focus and pay attention to the health check where it comes to internal five properties were used:

  • Health Check logo name
  • Creating IHealthCheck examples
  • Health check-out time (to prevent us because of health checks and take up too much resources)
  • Failed state logo
  • A label set (may be used for the health check filtering)

The five attributes associated source code is as follows:

   1:  public Func<IServiceProvider, IHealthCheck> Factory
   2:  {
   3:      get => _factory;
   4:      set
   5:      {
   6:          if (value == null)
   7:          {
   8:              throw new ArgumentNullException(nameof(value));
   9:          }
  10:      
  11:          _factory = value;
  12:      }
  13:  }
  14:      
  15:  public HealthStatus FailureStatus { get; set; }
  16:      
  17:  public TimeSpan Timeout
  18:  {
  19:      get => _timeout;
  20:      set
  21:      {
  22:          if (value <= TimeSpan.Zero && value != System.Threading.Timeout.InfiniteTimeSpan)
  23:          {
  24:              throw new ArgumentOutOfRangeException(nameof(value));
  25:          }
  26:      
  27:          _timeout = value;
  28:      }
  29:  }
  30:      
  31:  public string Name
  32:  {
  33:      get => _name;
  34:      set
  35:      {
  36:          if (value == null)
  37:          {
  38:              throw new ArgumentNullException(nameof(value));
  39:          }
  40:      
  41:          _name = value;
  42:      }
  43:  }
  44:      
  45:  public ISet<string> Tags { get; }

 

HealthCheckResult

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

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

  • 组件的当前状态
  • 异常信息
  • 友好的描述信息(不管是异常还是正常)
  • 额外可描述当前组件的键值对,这是一个开放式的属性,方面我们记录更多信息

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

   1:  public struct HealthCheckResult
   2:  {
   3:      private static readonly IReadOnlyDictionary<string, object> _emptyReadOnlyDictionary = new Dictionary<string, object>();
   4:   
   5:      public HealthCheckResult(HealthStatus status, string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)
   6:      {
   7:          Status = status;
   8:          Description = description;
   9:          Exception = exception;
  10:          Data = data ?? _emptyReadOnlyDictionary;
  11:      }
  12:   
  13:      public IReadOnlyDictionary<string, object> Data { get; }
  14:   
  15:      public string Description { get; }
  16:   
  17:      public Exception Exception { get; }
  18:   
  19:      public HealthStatus Status { get; }
  20:   
  21:      public static HealthCheckResult Healthy(string description = null, IReadOnlyDictionary<string, object> data = null)
  22:      {
  23:          return new HealthCheckResult(status: HealthStatus.Healthy, description, exception: null, data);
  24:      }
  25:   
  26:      public static HealthCheckResult Degraded(string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)
  27:      {
  28:          return new HealthCheckResult(status: HealthStatus.Degraded, description, exception: exception, data);
  29:      }
  30:      
  31:      public static HealthCheckResult Unhealthy(string description = null, Exception exception = null, IReadOnlyDictionary<string, object> data = null)
  32:      {
  33:          return new HealthCheckResult(status: HealthStatus.Unhealthy, description, exception, data);
  34:      }
  35:  }

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

HealthStatus的源码如下:

   1:  public enum HealthStatus
   2:  {
   3:      Unhealthy = 0,
   4:   
   5:      Degraded = 1,
   6:   
   7:      Healthy = 2,
   8:  }

IHealthCheckPublisher

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

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

  • 额外可描述当前组件的键值对,这是一个开放式的属性,方面我们记录更多信息
  • 友好的描述信息(不管是异常还是正常)
  • 组件的当前状态
  • 异常信息
  • 当前这次检查所耗费的时间
  • 相关的标签信息

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

   1:  public sealed class HealthReport
   2:  {
   3:      public HealthReport(IReadOnlyDictionary<string, HealthReportEntry> entries, TimeSpan totalDuration)
   4:      {
   5:          Entries = entries;
   6:          Status = CalculateAggregateStatus(entries.Values);
   7:          TotalDuration = totalDuration;
   8:      }
   9:   
  10:      public IReadOnlyDictionary<string, HealthReportEntry> Entries { get; }
  11:   
  12:      public HealthStatus Status { get; }
  13:   
  14:      public TimeSpan TotalDuration { get; }
  15:   
  16:      private HealthStatus CalculateAggregateStatus(IEnumerable<HealthReportEntry> entries)
  17:      {
  18:          var currentValue = HealthStatus.Healthy;
  19:          foreach (var entry in entries)
  20:          {
  21:              if (currentValue > entry.Status)
  22:              {
  23:                  currentValue = entry.Status;
  24:              }
  25:   
  26:              if (currentValue == HealthStatus.Unhealthy)
  27:              {
  28:                  // Game over, man! Game over!
  29:                  // (We hit the worst possible status, so there's no need to keep iterating)
  30:                  return currentValue;
  31:              }
  32:          }
  33:   
  34:          return currentValue;
  35:      }
  36:  }

总结

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

Guess you like

Origin www.cnblogs.com/edison0621/p/11968102.html