ASP .NET Core 健康檢查

簡介

健康檢查,其實這個名稱已經很明確了,它是檢查你的應用程序是否健康運行的一種方式。隨着當前各類項目越來越多的應用程序正在轉向微服務式架構,健康檢查就變得尤爲關鍵。雖然微服務體系結構具有許多好處,但其中一個缺點就是爲了確保所有這些服務都正常運行的操作開銷更高。你不在是監視一個龐大的整體項目的健康狀況,而是需要監控許多不同服務的狀態,甚至這些服務通常只負責一件事情。健康檢查(Heatlh Checks)通常與一些服務發現工具結合使用,如Consul ,來監控您的微服務器,來觀測您的服務是否健康運行。

健康檢查有很多種不同的方法,但最常見的方法是將HTTP端點暴露給專門用於健康檢查的應用程序。一般來說,如果一切情況都很好,你的服務將返回200的狀態碼,然而任何非200的代碼則意味着出現問題。例如,如果發生錯誤,你可能會返回500以及一些出錯的JSON信息。

舉例一些常見的健康檢查內容:

  • 檢查我的服務可以連接到數據庫嗎?
  • 檢查我的服務可以查詢第三方API嗎?
    • 可能做一些只讀操作
  • 我的服務可以訪問文件系統嗎(IO是否正常)?
  • 檢查我的服務佔用的內存或CPU是否高於某個閾值?

健康檢查有三個登記

  • Healthy 健康
  • Unhealthy 不良
  • Degraded 降級

ASP.NET Core實現

Neget安裝以下包

AspNetCore.HealthChecks.UI		
AspNetCore.HealthChecks.UI.Client
AspNetCore.HealthChecks.UI.InMemory.Storage
Microsoft.Extensions.Diagnostics.HealthChecks

添加檢查測試案例

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("健康"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("不良"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Degraded("降級"), tags: new[] { "baz_tag" });

添加檢查

using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace WebApplication6.HealthChecks
{
    public class DatabaseHealthCheck : IHealthCheck
    {
        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken =
         default)
        {
            try
            {
                return Task.FromResult(HealthCheckResult.Healthy($"API is running."));

            }
            catch (Exception ex)
            {

                return Task.FromResult(HealthCheckResult.Unhealthy("DB is not Healthy", ex));
            }
        }
    }
}

appsettings.json添加HealthChecksUI配置

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "HealthChecks-UI": {
    "HealthChecks": [
      {
        "Name": "Local",
        "Uri": "http://localhost:5000/health"
      }
      //{
      //  "Name": "",
      //  "Uri": ""
      //}
    ],
    "Webhooks": [
      {
        "Name": "",
        "Uri": "",
        "Payload": "",
        "RestoredPayload": ""
      }
    ],
    "EvaluationTimeOnSeconds": 10,
    "MinimumSecondsBetweenFailureNotifications": 60
  }
}

Startup添加HealthCheck服務和HealthCheckUI界面

using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using WebApplication6.HealthChecks;

namespace WebApplication6
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }


        public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();


            services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("健康"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("不良"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Degraded("降級"), tags: new[] { "baz_tag" });

            //添加DatabaseHealthCheck,30S輪詢健康檢查一次
            services.AddHealthChecks().AddCheck<DatabaseHealthCheck>(nameof(DatabaseHealthCheck));

            //需要安裝Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore包
            //.AddDbContextCheck<Microsoft.EntityFrameworkCore.DbContext>("DbContext"); 

            //添加UI 內存存儲
            services.AddHealthChecksUI().AddInMemoryStorage();

        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();



            app.UseHealthChecksUI();
            HealthCheckOptions healthCheckOptions = new HealthCheckOptions
            {
                AllowCachingResponses = false,
                Predicate = _ => true,
                ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
                ResultStatusCodes =
                {
                    [HealthStatus.Healthy] = StatusCodes.Status200OK,
                    [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable,
                    [HealthStatus.Degraded] = StatusCodes.Status500InternalServerError,
                    [HealthStatus.Degraded] = StatusCodes.Status419AuthenticationTimeout
                }
            };

            app.UseHealthChecks("/health", healthCheckOptions);



            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

訪問http://localhost:5000/health查看健康檢查

訪問http://localhost:5000/healthchecks-ui查看健康檢查UI界面

主動健康檢查

主動健康檢查進行有兩種方式

  • 訪問http://localhost:5000/health健康檢查地址
  • Controller訪問以下Api
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System.Net;

namespace WebApplication2.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class HealthController : ControllerBase
    {
        private readonly HealthCheckService _healthCheckService;
        public HealthController(HealthCheckService healthCheckService) => _healthCheckService = healthCheckService;


        [HttpGet]
        public async Task<IActionResult> Get()
        {
            var report = await _healthCheckService.CheckHealthAsync();

            return report.Status == HealthStatus.Healthy ? Ok(report) : StatusCode((int)HttpStatusCode.ServiceUnavailable, report);
        }
    }
}

程序自身健康檢查

using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace WebApplication6.HealthChecks
{
    public class DelayStartupHealthCheck : IHealthCheck
    {

        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken =
          default)
        {
            if (DelayStartup.StartupReady)
            {
                return Task.FromResult(HealthCheckResult.Healthy());
            }
            return Task.FromResult(HealthCheckResult.Unhealthy());
        }
    }
    public class DelayStartup
    {
        public static bool StartupReady { get; private set; } = false;

        private static long DelaySeconds = 60;

        private static Semaphore semaphore = new Semaphore(0, 1);

        static DelayStartup()
        {
            try
            {
                //IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
                //DelaySeconds = int.Parse(configuration["App:DelayStartup"]);
                DelaySeconds = 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                DelaySeconds = 0;
            }
            if (DelaySeconds > 0)
            {
                Startup();
            }
            else
            {
                StartupReady = true;
            }
        }

        private static void Startup()
        {
            DateTime start = DateTime.Now;

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    if (DateTime.Now.Subtract(start).TotalSeconds >= DelaySeconds)
                    {
                        StartupReady = true;
                        Console.WriteLine("DelayStartup StartupReady");
                        break;
                    }
                    Console.WriteLine("DelayStartup Checking");
                    semaphore.WaitOne(2000);
                }
            });
        }
    }
}

Neget包

Neget包地址

#主包
Install-Package Microsoft.Extensions.Diagnostics.HealthChecks

#UI
Install-Package AspNetCore.HealthChecks.UI
Install-Package AspNetCore.HealthChecks.UI.Client

#UI存儲
Install-Package AspNetCore.HealthChecks.UI.InMemory.Storage
Install-Package AspNetCore.HealthChecks.UI.SqlServer.Storage
Install-Package AspNetCore.HealthChecks.UI.SQLite.Storage
Install-Package AspNetCore.HealthChecks.UI.PostgreSQL.Storage
Install-Package AspNetCore.HealthChecks.UI.MySql.Storage

#HealthCheckReport 發送
Install-Package AspNetcore.HealthChecks.Publisher.ApplicationInsights
Install-Package AspNetcore.HealthChecks.Publisher.CloudWatch
Install-Package AspNetcore.HealthChecks.Publisher.Datadog
Install-Package AspNetcore.HealthChecks.Publisher.Prometheus
Install-Package AspNetcore.HealthChecks.Publisher.Seq

#健康檢查
Install-Package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
Install-Package AspNetCore.HealthChecks.ApplicationStatus
Install-Package AspNetCore.HealthChecks.ArangoDb
Install-Package AspNetCore.HealthChecks.Aws.S3
Install-Package AspNetCore.HealthChecks.Aws.SecretsManager
Install-Package AspNetCore.HealthChecks.Aws.Sns
Install-Package AspNetCore.HealthChecks.Aws.Sqs
Install-Package AspNetCore.HealthChecks.Aws.SystemsManager
Install-Package AspNetCore.HealthChecks.Azure.IoTHub
Install-Package AspNetCore.HealthChecks.AzureDigitalTwin
Install-Package AspNetCore.HealthChecks.AzureKeyVault
Install-Package AspNetCore.HealthChecks.AzureServiceBus
Install-Package AspNetCore.HealthChecks.AzureStorage
Install-Package AspNetCore.HealthChecks.Consul
Install-Package AspNetCore.HealthChecks.CosmosDb
Install-Package AspNetCore.HealthChecks.DocumentDb
Install-Package AspNetCore.HealthChecks.DynamoDB
Install-Package AspNetCore.HealthChecks.Elasticsearch
Install-Package AspNetCore.HealthChecks.EventStore
Install-Package AspNetCore.HealthChecks.EventStore.gRPC
Install-Package AspNetCore.HealthChecks.Gcp.CloudFirestore
Install-Package AspNetCore.HealthChecks.Gremlin
Install-Package AspNetCore.HealthChecks.Hangfire
Install-Package AspNetCore.HealthChecks.IbmMQ
Install-Package AspNetCore.HealthChecks.Kafka
Install-Package AspNetCore.HealthChecks.Kubernetes
Install-Package AspNetCore.HealthChecks.MongoDb
Install-Package AspNetCore.HealthChecks.MySql
Install-Package AspNetCore.HealthChecks.Nats
Install-Package AspNetCore.HealthChecks.Network
Install-Package AspNetCore.HealthChecks.Npgsql
Install-Package AspNetCore.HealthChecks.OpenIdConnectServer
Install-Package AspNetCore.HealthChecks.Oracle
Install-Package AspNetCore.HealthChecks.RabbitMQ
Install-Package AspNetCore.HealthChecks.RavenDB
Install-Package AspNetCore.HealthChecks.Redis
Install-Package AspNetCore.HealthChecks.SendGrid
Install-Package AspNetCore.HealthChecks.SignalR
Install-Package AspNetCore.HealthChecks.Solr
Install-Package AspNetCore.HealthChecks.SqLite
Install-Package AspNetCore.HealthChecks.SqlServer
Install-Package AspNetCore.HealthChecks.System
Install-Package AspNetCore.HealthChecks.Uris

相關網址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章