天天看點

asp.netcore 實作健康檢測

建議大家使用VS2019開發時把自帶的反編譯功能打開:

asp.netcore 實作健康檢測
進入正題,首先上一個本節最終能實作的健康檢測UI界面:
asp.netcore 實作健康檢測
本節實作的健康檢測是通過引用以下系列nuget進行的實作:
asp.netcore 實作健康檢測

github上有該包的實作方式,使用過程中可以參考源碼來編寫相關參數,github位址:https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks

在此也列一下清單吧,總共實作了對以下功能點的健康檢測功能:

asp.netcore 實作健康檢測

以上主要是些通用的檢測點,如api是否正常,資料庫、redis等存儲庫是否正常,rabbitmq是否正常等,除此之後我們還可以自己擴充,比如與我們系統業務相關的功能資料檢測等,簡單的實作估計也就幾行代碼,主要看需求。

如何實作web或api、資料庫、redis等的狀态檢測呢?下面開始各種配置。

  • 首先還是引用nuget包,我是引用了以下一堆,用哪個還是看需求:
asp.netcore 實作健康檢測
  • 配置Startup.cs檔案:
1     public class Startup
 2     {
 3         public Startup(IConfiguration configuration)
 4         {
 5             Configuration = configuration;
 6         }
 7         public IConfiguration Configuration { get; }
 8 
 9         public void ConfigureServices(IServiceCollection services)
10         {
11             services.AddCustomHealthCheck(this.Configuration);
12 
13             services.AddHealthChecksUI(setupSettings =>
14             {
15                 //檢測站點,可以添加多條,UI中會把站點内的檢測點分組顯示(也可通過配置檔案實作)
16                 setupSettings.AddHealthCheckEndpoint(name: "localhost-5000", uri: "http://localhost:5000/health");
17                 //當檢測出異常結果時發送消息給api
18                 setupSettings.AddWebhookNotification("webhook1",
19                     uri: "http://localhost:5008/WeatherForecast/message",
20                     payload: "{ \"message\": \"Webhook report for [[LIVENESS]]: [[FAILURE]] - Description: [[DESCRIPTIONS]]\"}",
21                     restorePayload: "{ \"message\": \"[[LIVENESS]] is back to life\"}");
22                 setupSettings.SetMinimumSecondsBetweenFailureNotifications(60);
23                 setupSettings.SetEvaluationTimeInSeconds(10);
24             }).AddSqlServerStorage(Configuration["HealthStorageConnectionString"]);//資料庫持久化
25             //.AddInMemoryStorage();//記憶體持久化
26         }
27 
28         public void ConfigureContainer(ContainerBuilder builder)
29         {
30             //autofac
31         }
32 
33         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
34         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
35         {
36             if (env.IsDevelopment())
37             {
38                 app.UseDeveloperExceptionPage();
39             }
40 
41             app.UseRouting();
42             app.UseEndpoints(endpoints =>
43             {
44                 endpoints.MapHealthChecks("/health", new HealthCheckOptions()
45                 {
46                     Predicate = _ => true,
47                     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
48                 });
49                 endpoints.MapHealthChecksUI();
50             });
51         }
52     }      

其中AddCustomHealthCheck的實作如下,實作的檢測執行個體:

1         public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
 2         {
 3             var hcBuilder = services.AddHealthChecks();
 4 
 5             hcBuilder.AddCheck("Jobs.MicrosoftBackgroundService-apiself", () => HealthCheckResult.Healthy());
 6             hcBuilder.AddSqlServer(
 7                     configuration["ConnectionString"],
 8                     name: "Jobs.MicrosoftBackgroundService-sqlserver-check",
 9                     tags: new string[] { "sqlserverdb" });
10             hcBuilder.AddRabbitMQ(
11                     $"amqp://{configuration["EventBusConnection"]}",
12                     name: "Jobs.MicrosoftBackgroundService-rabbitmqbus-check",
13                     tags: new string[] { "rabbitmqbus" });
14             hcBuilder.AddRedis(
15                 configuration["RedisConnectionString"],
16                 name: "Jobs.MicrosoftBackgroundService-redis-check",
17                 tags: new string[] { "redisdb" });
18             hcBuilder.AddUrlGroup(new Uri(configuration["testApiUrl"]), name: "testApiUrl-check", tags: new string[] { "testApiUrl" });
19 
20             return services;
21         }      

可以看到這裡實作了對sqlserver資料庫、rebbitmq、redis、webapi的健康檢測,參數中最重要的是名稱及配置如連接配接字元串的資訊,如redis的連接配接字元串格式如何寫,我們可以通過檢視源碼來了解,此處實作redis的健康檢測源碼如下:

1 using Microsoft.Extensions.Diagnostics.HealthChecks;
 2 using StackExchange.Redis;
 3 using System;
 4 using System.Collections.Concurrent;
 5 using System.Threading;
 6 using System.Threading.Tasks;
 7 
 8 namespace HealthChecks.Redis
 9 {
10     public class RedisHealthCheck : IHealthCheck
11     {
12         private static readonly ConcurrentDictionary<string, ConnectionMultiplexer> _connections = new ConcurrentDictionary<string, ConnectionMultiplexer>();
13 
14         private readonly string _redisConnectionString;
15 
16         public RedisHealthCheck(string redisConnectionString)
17         {
18             _redisConnectionString = (redisConnectionString ?? throw new ArgumentNullException("redisConnectionString"));
19         }
20 
21         public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken))
22         {
23             _ = 1;
24             try
25             {
26                 if (!_connections.TryGetValue(_redisConnectionString, out ConnectionMultiplexer value))
27                 {
28                     value = await ConnectionMultiplexer.ConnectAsync(_redisConnectionString);
29                     if (!_connections.TryAdd(_redisConnectionString, value))
30                     {
31                         value.Dispose();
32                         value = _connections[_redisConnectionString];
33                     }
34                 }
35 
36                 await value.GetDatabase().PingAsync();
37                 return HealthCheckResult.Healthy();
38             }
39             catch (Exception exception)
40             {
41                 return new HealthCheckResult(context.Registration.FailureStatus, null, exception);
42             }
43         }
44     }
45 }      

實作就幾行的代碼,同時我們看到這裡是通過StackExchange.Redis實作的redis連接配接,我們傳遞的連接配接字元串就很明顯了,如下:

"RedisConnectionString": "192.168.217.128:6379,defaultDatabase=1,password=123!@#..."      

其他的相關參數也可以通過檢視源碼的方式來進行操作。。。

----------------------------------------------------------------------------------------------------------------------------------

設定資料持久化,可以通過檢視源碼得知此處是使用的EFCore,支援以下種類的持久化:

asp.netcore 實作健康檢測

services中添加配置(記得引用需要的持久化nuget包):

services.AddSqlServerStorage(Configuration["HealthStorageConnectionString"]);      

程式啟動後會自動根據配置的資料庫連接配接資訊建立資料表,大概就是配置資訊、目前狀态資訊、曆史記錄資訊。

如果健康檢測異常需要發送消息至api,可以添加以下配置:

asp.netcore 實作健康檢測

具體參數格式也可通過源碼檢視,此處是post方式資料傳輸,關鍵源碼如下:

1                 foreach (var webHook in _settings.Webhooks)
 2                 {
 3                     bool shouldNotify = webHook.ShouldNotifyFunc?.Invoke(report) ?? true;
 4 
 5                     if (!shouldNotify)
 6                     {
 7                         _logger.LogInformation("Webhook notification will not be sent because of user configuration");
 8                         continue;
 9                     };
10 
11                     if (!isHealthy)
12                     {
13                         failure = webHook.CustomMessageFunc?.Invoke(report) ?? GetFailedMessageFromContent(report);
14                         description = webHook.CustomDescriptionFunc?.Invoke(report) ?? GetFailedDescriptionsFromContent(report);
15                     }
16 
17                     var payload = isHealthy ? webHook.RestoredPayload : webHook.Payload;
18                     payload = payload.Replace(Keys.LIVENESS_BOOKMARK, name)
19                         .Replace(Keys.FAILURE_BOOKMARK, failure)
20                         .Replace(Keys.DESCRIPTIONS_BOOKMARK, description);
21 
22 
23                     Uri.TryCreate(webHook.Uri, UriKind.Absolute, out var absoluteUri);
24 
25                     if (absoluteUri == null || !absoluteUri.IsValidHealthCheckEndpoint())
26                     {
27                         Uri.TryCreate(_serverAddressesService.AbsoluteUriFromRelative(webHook.Uri), UriKind.Absolute, out absoluteUri);
28                     }
29 
30                     await SendRequest(absoluteUri, webHook.Name, payload);
31                 }

可以看到此處的Webhooks可以配置多個      
1         private async Task SendRequest(Uri uri, string name, string payloadContent)
 2         {
 3             try
 4             {
 5                 var payload = new StringContent(payloadContent, Encoding.UTF8, Keys.DEFAULT_RESPONSE_CONTENT_TYPE);
 6                 var response = await _httpClient.PostAsync(uri, payload);
 7                 if (!response.IsSuccessStatusCode)
 8                 {
 9                     _logger.LogError("The webhook notification has not executed successfully for {name} webhook. The error code is {statuscode}.", name, response.StatusCode);
10                 }
11 
12             }
13             catch (Exception exception)
14             {
15                 _logger.LogError($"The failure notification for {name} has not executed successfully.", exception);
16             }
17         }      

我們可以通過api接收異常消息後添加日志或進行發送郵件等提醒資訊。

 最後如果要配置UI界面,隻需在endpoint中添加配置:

1             app.UseEndpoints(endpoints =>
2             {
3                 endpoints.MapHealthChecks("/health", new HealthCheckOptions()
4                 {
5                     Predicate = _ => true,
6                     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
7                 });//要進行該站點檢測應添加此代碼
8                 endpoints.MapHealthChecksUI();//添加UI界面支援
9             });      

寫的比較散,希望對大家學習有一絲絲幫助~~

作者:屈魯奇

出處:https://www.cnblogs.com/quluqi

聯系:[email protected] QQ:496195435

本文版權歸作者和部落格園共有,歡迎轉載,但必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。如有問題或建議,請多多賜教,非常感謝。

繼續閱讀