.Net Core實現健康檢查

  • 2019 年 11 月 3 日
  • 筆記

ASP.NET Core 提供運行狀況檢查中間件和庫,以用於報告應用基礎結構組件的運行狀況。
運行狀況檢查由應用程式作為 HTTP 終結點公開。 可以為各種實時監視方案配置運行狀況檢查終結點:

  • 運行狀況探測可以由容器業務流程協調程和負載均衡器用於檢查應用的狀態。 例如,容器業務流程協調程式可以通過停止滾動部署或重新啟動容器來響應失敗的運行狀況檢查。 負載均衡器可以通過將流量從失敗的實例路由到正常實例,來應對不正常的應用。
  • 可以監視記憶體、磁碟和其他物理伺服器資源的使用情況來了解是否處於正常狀態。
  • 運行狀況檢查可以測試應用的依賴項(如資料庫和外部服務終結點)以確認是否可用和正常工作。

這個示例展示資料庫的運行狀態,他在其驗證資料庫連接並返回相應的結果

        [Route("health")]          public ActionResult Health()          {              using (var connection = new SqlConnection("Server=.;Initial Catalog=master;Integrated Security=true"))              {                  try                  {                      connection.Open();                  }                  catch (SqlException)                  {                      return new StatusCodeResult(503);                    }              }                return new EmptyResult();          }  

當我們請求該地址的時候時,如果連接到資料庫時出現任何連接問題,它將顯示一條包含200狀態程式碼和503狀態程式碼的空消息​​。

image

image

現在基於這些結果狀態碼,我們可以監視系統採取相關的操作。

從.NET Core2.2開始,我們不需要為運行狀態在去自定義檢查控制器和介面,而是框架本身已經為我們提供了運行狀況的檢查服務。

安裝和運行

Install-Package Microsoft.Extensions.Diagnostics.HealthChecks

安裝後,我們需要在Startup.cs文件的ConfigureServices()和Configure()方法中添加。

        public void ConfigureServices(IServiceCollection services)          {              services.AddHealthChecks();          }          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)          {              app                  .UseHealthChecks("/health");            }    

我們在configure()方法中配置完端點後,我們就可以通過 /health來請求查看我們的應用程式的健康程度的。

image

但是這樣對於我們剛才的需求是滿足不了的,那麼我們如何自定義我們的健康度檢查呢?

兩種方式來處理

option 1

        public void ConfigureServices(IServiceCollection services)          {              services.AddHealthChecks()    .AddCheck("sql", () =>    {          using (var connection = new SqlConnection("Server=.;Initial Catalog=master;Integrated Security=true"))        {            try            {                connection.Open();            }            catch (SqlException)            {                return HealthCheckResult.Unhealthy();            }        }          return HealthCheckResult.Healthy();      });          }  

在這裡我們使用匿名方法AddCheck(),來編寫我們的自定義的驗證邏輯,結果是HealthCheckResult對象,該對象包含3個選項

  1. Healthy 健康
  2. Unhealthy 不良
  3. Degraded 降級

option 2

實現IHealthCheck介面並實現CheckHealthAsync()方法,如下所示:

   public class DatabaseHealthCheck : IHealthCheck          {              public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken =               default)              {                  using (var connection = new SqlConnection("Server=.;Initial Catalog=master;Integrated Security=true"))                  {                      try                      {                          connection.Open();                      }                      catch (SqlException)                      {                          return  Task.FromResult(HealthCheckResult.Unhealthy());                      }                  }                    return Task.FromResult(HealthCheckResult.Healthy());                }          }

創建該類之後,我們需要通過使用一些有效的唯一名稱,AddCheck ()方法在ConfigureServices()方法中提及該類,如下所示。

     public void ConfigureServices(IServiceCollection services)          {              services.AddHealthChecks()            .AddCheck<DatabaseHealthCheck>("sql");          }

現在我們的程式碼就寫完了,我們可以像上面那樣添加任意數量的Health Task,它將按照我們在此處聲明的順序運行。

自定義狀態碼

在之前我們也說過200為健康,503為不健康那麼Healthcheck服務甚至通過以下方式使用其options對象提供自定義狀態程式碼,為我們提供了更改此默認的狀態碼。

config.MapHealthChecks("/health", new HealthCheckOptions                       {                          ResultStatusCodes = new Dictionary<HealthStatus, int> { { HealthStatus.Unhealthy, 420 }, { HealthStatus.Healthy, 200 }, { HealthStatus.Degraded, 419 } }                           }); 

自定義輸出

我們可以自定義輸出,以獲取有關每個運行狀況檢查任務的更清晰詳細的資訊。如果我們有多個運行狀況檢查任務來分析哪個任務使整個服務健康狀態變為」不正常「,這將非常有用。

我們可以通過HealthCheckOptions ResponseWriter屬性來實現。

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)          {              app                   .UseRouting()                   .UseEndpoints(config =>                   {                       config.MapHealthChecks("/health", new HealthCheckOptions                       {                          ResponseWriter=CustomResponseWriter                         });                     });            }          private static Task CustomResponseWriter(HttpContext context, HealthReport healthReport)          {              context.Response.ContentType = "application/json";                var result = JsonConvert.SerializeObject(new              {                  status = healthReport.Status.ToString(),                  errors = healthReport.Entries.Select(e => new                  {                      key = e.Key,                      value = e.Value.Status.ToString()                  })              });              return context.Response.WriteAsync(result);            }

image

現在以json顯示我們的詳細資訊,完成了健康狀態的檢查.

健康檢查介面

Install-Package AspNetCore.HealthChecks.UI

安裝完成後,需要相應地在ConfigureServices()和Configure()方法中調用相應的服務方法。

public void ConfigureServices(IServiceCollection services)  {      services.AddHealthChecksUI();  }    public void Configure(IApplicationBuilder app, IHostingEnvironment env)  {      app.UseHealthChecksUI();  }  

配置完成後,您可以運行應用程式並指向/ healthchecks-ui地址,該端點顯示如下的UI.

image

但是介面上沒有我們剛才自定義的,那我們在進行配置

Appsetting.json

{    "ApplicationInsights": {      "InstrumentationKey": "your-instrumentation-key"    },    "Logging": {      "LogLevel": {        "Default": "Warning"      }    },    "AllowedHosts": "*",    "HealthChecksUI": {      "HealthChecks": [        {          "Name": "Test Health",          "Uri": "https://localhost:44342/health"        }      ],      "EvaluationTimeinSeconds": 10,      "MinimumSecondsBetweenFailureNotifications": 60    }  }  

image

這樣就可以看到健康狀態了

Tags: