zoukankan      html  css  js  c++  java
  • asp.netcore 实现健康检测

    建议大家使用VS2019开发时把自带的反编译功能打开:

    进入正题,首先上一个本节最终能实现的健康检测UI界面:

    本节实现的健康检测是通过引用以下系列nuget进行的实现:

    github上有该包的实现方式,使用过程中可以参考源码来编写相关参数,github地址:https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks

    在此也列一下清单吧,总共实现了对以下功能点的健康检测功能:

    以上主要是些通用的检测点,如api是否正常,数据库、redis等存储库是否正常,rabbitmq是否正常等,除此之后我们还可以自己扩展,比如与我们系统业务相关的功能数据检测等,简单的实现估计也就几行代码,主要看需求。

    如何实现web或api、数据库、redis等的状态检测呢?下面开始各种配置。

    • 首先还是引用nuget包,我是引用了以下一堆,用哪个还是看需求:

    • 配置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,支持以下种类的持久化:

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

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

    程序启动后会自动根据配置的数据库连接信息创建数据表,大概就是配置信息、当前状态信息、历史记录信息。

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

    如果健康检测异常需要发送消息至api,可以添加以下配置:

    具体参数格式也可通过源码查看,此处是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             });

    写的比较散,希望对大家学习有一丝丝帮助~~

  • 相关阅读:
    课后作业成绩汇总
    关于作业提交要求声明 2017-09-22
    团队编程项目作业成绩汇总
    结对项目作业成绩汇总
    团队组信息
    小知识记录:第XI篇
    小知识记录:第X篇
    小知识记录:第十二篇
    小知识记录:第十一篇
    小知识记录:第十篇
  • 原文地址:https://www.cnblogs.com/quluqi/p/13251547.html
Copyright © 2011-2022 走看看