.net core 健康检测 电脑版发表于:2020/8/2 17:44 ![.netcore](https://img.tnblog.net/arcimg/hb/c857299a86d84ee7b26d181a31e58234.jpg ".netcore") >#.net core 健康检测 [TOC] 检查应用的健康状态 ------------ tn>ASP.NET Core 框架的健康检查功能是通过 `HealthCheckMiddleware` 中间件完成的。我们不仅可以利用该中间件确定当前应用的可用性,还可以注册相应的 `IHealthCheck` 对象来完成针对不同方面的健康检查。例如,当前应用部署或者依赖一些组件或者服务,我们可以注册相应的 `IHealthCheck` 对象来完成针对它们的健康检查。下面通过实例演示一些典型的健康检查应用场景。<br/> GitHub:https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks 确定当前应用是否可用 ------------ tn>对于部署于集群或者容器的应用或者服务来说,它需要对外暴露一个终结点,以便负载均衡器或者容器编排框架可以利用该终结点是否可用。ASP.NET Core 可以通过如下所示的编程方式来提供这个健康检查终结点。 ```csharp class Program { static void Main(string[] args) { Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder=>builder .ConfigureServices(svcs=>svcs.AddHealthChecks()) .Configure(app=>app.UseHealthChecks("/healthcheck"))) .Build() .Run(); } } ``` tn>从上面的代码来看,我们通过 `IServiceCollection`接口的 `AddHealthChecks` 扩展方法注册 `IHealthChecksBuilder` 健康检查的服务,再通过 `IApplicationBuilder` 接口的 `UseHealthChecks` 扩展方法注册 `HealthChecksMiddle` 中间件,其中参数 `/healthcheck` 表示检查健康终结点的访问路径,最后我们只需要 Get 访问该路径便可知当前的健康状态(结果如下图所示)。 ![简单举例结果](https://img.tnblog.net/arcimg/hb/2f348169616d4439be60e1e11b0ae70c.png "简单举例结果") tn>如下所显示的图片是我们请求健康检查后得到的报文,这里我们可以看到这是一个响应码`200OK`媒体类型为 `text\planin` 说明是以文本输出的格式。通过健康检查我们想获取的是当前应用程序的状态,所以我们是不需要缓存内容的,在响应的报文中`Pragma` 和 `Cache-Control`的报头恰好说明了这一点。 ![](https://img.tnblog.net/arcimg/hb/569086724fc742718d5ba6d8beebc4ad.png) 定制健康检查逻辑 ------------ tn>生活中,我们经常也会更具自身的需求进行选择不同食物用膳,健康检查也是如此。在上一个案例中应用程序一旦启动成功所请求的状态就是`Healthy`,如果我们需要在程序启动之前定制一些条件再进行判断是否健康,那这就不符合需求了。 <br/> tn>在下面的案例中,我们通过 `IServiceCollection` 接口的 `AddHealthChecks` 扩展方法注册所需的服务依赖之后,返回 `IHealthChecksBuilder` 对象的 `AddCheck` 方法注册了一个 `IHealthCheck` 对象,该对象会调用 `Check` 方法来决定最终的健康状态。在内嵌的 `Check` 方法中,该方法会返回 3 种健康状态(Healthy、UnHealthy、Degraded) ```csharp class Program { static void Main(string[] args) { var random = new Random(); Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder=>builder .ConfigureServices(svcs=>svcs.AddHealthChecks() .AddCheck("default",Check)) .Configure(app=>app.UseHealthChecks("/healthcheck"))) .Build() .Run(); HealthCheckResult Check() { return (random.Next(1,4)) switch { 1 => HealthCheckResult.Unhealthy(), 2 => HealthCheckResult.Degraded(), _ => HealthCheckResult.Healthy() }; } } } ``` tn>从如上所示的代码中有3种健康检查状态的响应报文。`Healthy` 与 `Degraded` 响应的都是 `200 Ok`,它们都表示是可用(Available)状态,两者之间的区别在于**完全可用**与**部分可用**, `Unhealthy` 的服务被视为不可用(Unavailable),所以响应状态码为 `Service Unabailable` ![](https://img.tnblog.net/arcimg/hb/1b120bb77ad040daa13cc949a092ecba.png) ![](https://img.tnblog.net/arcimg/hb/d588981f2da741759c8d8d4d60739505.png) 改变响应状态码 ------------ tn>上面讲解了3种健康检查与所对应的状态码,默认的状态码虽然是一种规范,但还是无法分辨出 `Healthy` 与 `Degraded`,所以我们可用通过自定义不同但状态码进行区分。 ```csharp class Program { static void Main(string[] args) { var random = new Random(); var option = new HealthCheckOptions{ ResultStatusCodes = new Dictionary<HealthStatus,int>{ [HealthStatus.Healthy] = 99, [HealthStatus.Degraded] = 299, [HealthStatus.Unhealthy] = 503 } }; Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder=>builder .ConfigureServices(svcs=>svcs.AddHealthChecks() .AddCheck("default",Check)) .Configure(app=>app.UseHealthChecks("/healthcheck",option))) .Build() .Run(); HealthCheckResult Check() { return (random.Next(1,4)) switch { 1 => HealthCheckResult.Unhealthy(), 2 => HealthCheckResult.Degraded(), _ => HealthCheckResult.Healthy() }; } } } ``` tn> `HealthChecksMiddleware` 提供了 `HealthCheckOptions` 对象作为对应的配置选项。`HealthCheckOptions` 对象通过 `ResultStatusCodes` 属性字段返回的字典维护了3种健康状态与所对应的状态码,这里我们只修改 `Healthy` 与 `Degraded` 这两种健康状态的状态码,分别为 **99** 与 **299**。 ![Healthy](https://img.tnblog.net/arcimg/hb/6ec3dd77e08849b9ac50d76288270a43.png "Healthy") ![Degraded](https://img.tnblog.net/arcimg/hb/25d2609f48e34f659876e030a5646fc3.png "Degraded") 细粒度的健康检查 ------------ tn>如果当应用的本身依赖了其他服务与组件时,这个时候就可以针对它们做细粒度的健康检查。前面通过 `IHealthCheck` 对象对应用级别的健康检查做了定制,同样我们可以通过 `IHealthCheck` 对象对某个组件或者服务注册相应对 `IHealthCheck` 对象来确定它们的健康状态。 ```csharp class Program { static void Main(string[] args) { var random = new Random(); Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder=>builder .ConfigureServices(svcs=>svcs.AddHealthChecks() .AddCheck("aaa",Check) .AddCheck("bbb",Check) .AddCheck("ccc",Check)) .Configure(app=>app.UseHealthChecks("/healthcheck"))) .Build() .Run(); HealthCheckResult Check() { return (random.Next(1,4)) switch { 1 => HealthCheckResult.Unhealthy(), 2 => HealthCheckResult.Degraded(), _ => HealthCheckResult.Healthy() }; } } } ``` tn>这里以自定义的3个服务,通过3个 `IHealthCheck` 对象来完成对它们对健康检查。由于注册的 3 个 `IHealthCheck`采用的不同同一个 `Check` 方法决定最后的健康状态,所以也只有3种不同的结果。(这里我就不上图了) <br/> >从这个案例可以反应出所有得到的结果有点**以面盖全**了,如果是`Healthy`那么所有的服务以及所依赖的组件都是`Healthy`,...所以这并不是我们想要的,应该对服务与依赖进行定制响应内容。 定制响应内容 ------------ tn>上面演示的实例所得到的应用整体健康状态,如果要得到对服务与依赖的插件一份比较完整且详细“健康报告”,我们将程序做适当修改。 ```csharp class Program { static void Main(string[] args) { var random = new Random(); var options = new HealthCheckOptions{ ResponseWriter = ReportAsync }; Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder=>builder .ConfigureServices(svcs=>svcs.AddHealthChecks() .AddCheck("aaa",Check,new string[]{ "aaa1","bbb2" }) .AddCheck("bbb",Check,new string[]{ "bbb1","bbb2" }) .AddCheck("ccc",Check,new string[]{ "ccc1","ccc1" })) .Configure(app=>app.UseHealthChecks("/healthcheck",options))) .Build() .Run(); static Task ReportAsync(Microsoft.AspNetCore.Http.HttpContext content,HealthReport report){ content.Response.ContentType = "application/json"; var settings = new JsonSerializerSettings(); settings.Formatting = Formatting.Indented; settings.Converters.Add(new StringEnumConverter()); return content.Response.WriteAsync(JsonConvert.SerializeObject(report,settings)); } HealthCheckResult Check() { return (random.Next(1,4)) switch { 1 => HealthCheckResult.Unhealthy("Unavailable"), 2 => HealthCheckResult.Degraded("Degraded"), _ => HealthCheckResult.Healthy("Normal") }; } } } ``` tn>对改写的内容体现以下几点:首先,为 `Check` 方法返回的表示健康检查结果的 `HealthCheckResult` 对象设置对应的描述性文字(Normal、Degraded 和 Unavailable);其次,在调用 `IHealthChecksBuilder` 接口的 `AddCheck` 方法注册相应的 `IHealthCheck` 对象时,指定了两个的标签(Tag),如针对服务 `aaa` 的 `IHealthCheck` 对象的标签设置为 `aaa1` 和 `aaa2`; 最后,在调用 `IApplicationBuilder` 接口的 `UseHealthChecks` 扩展方法注册 `HealthCheckMiddleware` 中间件时,指定了作为配置选项的 `HealthCheckOptions` 对象,并通过设置其 `ResponseWriter` 属性的方式完成了对健康报告的呈现。 <br/> `HealthCheckOption` 的 `ResponseWriter` 属性返回的是一个 `Func<HttpContext,HealthReport,Task>` 对象,其中 `HealthReport` 对象是 `HealthCheckMiddleware` 中间件针对健康报告的表达。我们设置的委托对象应应对的方法为 `ReportAsync`,该方法会直接将指定的 `HealthReport` 对象序列化成 `JSON` 格式并作为响应主题内容。我们并没有设置相应的状态码,所以可以直接在浏览器种看到这份完整的健康报告。 ![](https://img.tnblog.net/arcimg/hb/9f3e4512a4ba48dd94f30c564101972d.png) 过滤 IHealthCheck 对象 ------------ tn>`HealthCheckMiddleware` 中间件提取注册的 `IHealthCheck` 对象完成具体的健康检查工作之前,我们可以做进一步过滤。对于 `IHealthCheck` 对象的过滤逻辑依然是利用 `HealthCheckOptions` 配置来进行实现,同时我们也需要设置它的 `Predicate` 属性,该属性返回一个 `Func<HealthCheckRegistration, bool>` 类型的委托对象,其中 `HealthCheckRegistration` 对象代表针对 `IHealthCheck` 对象的注册。 <br/> 在如下代码中我们通过设置配置选项 `HealthCheckOptions` 对象的 `Predicate` 属性使之选择 `Tag` 前缀不为 `ccc` 的 `IHealthCheck` 对象 ```csharp class Program { static void Main(string[] args) { var random = new Random(); var options = new HealthCheckOptions { ResponseWriter = ReportAsync, Predicate = reg => reg.Tags.Any(tag => !tag.StartsWith("ccc", StringComparison.OrdinalIgnoreCase)) }; Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .ConfigureServices(svcs => svcs .AddHealthChecks() .AddCheck("aaa", Check, new string[] { "aaa1", "bbb2" }) .AddCheck("bbb", Check, new string[] { "bbb1", "bbb2" }) .AddCheck("ccc", Check, new string[] { "ccc1", "ccc1" }) ) .Configure(app => app.UseHealthChecks("/healthcheck", options))) .Build() .Run(); static Task ReportAsync(Microsoft.AspNetCore.Http.HttpContext content, HealthReport report) { content.Response.ContentType = "application/json"; var settings = new JsonSerializerSettings(); settings.Formatting = Formatting.Indented; settings.Converters.Add(new StringEnumConverter()); return content.Response.WriteAsync(JsonConvert.SerializeObject(report, settings)); } HealthCheckResult Check() { return (random.Next(1, 4)) switch { 1 => HealthCheckResult.Unhealthy("Unavailable"), 2 => HealthCheckResult.Degraded("Degraded"), _ => HealthCheckResult.Healthy("Normal") }; } } } ``` tn>由于我们这里过滤了 `ccc` 服务的健康检查,所以在浏览器中我们就看不了所对应的健康状态。 ![](https://img.tnblog.net/arcimg/hb/995a7c726f654e6da7e2256811185778.png) 针对 Entity Framework Core 的健康检查 ------------ tn>如果应用需要用到对数据库的访问,那么就需要通过健康检查判断数据库的可用性。Entity Framework Core作为我们最常用数据库的存取框架,就可以利用健康检查来确定 `DbContext` 是否可用。针对 `DbContext` 的健康检查是通过 `DbContextHealthCheck<TContext>` 这个内部类型完成的,该类型由 NuGet 包 `Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore` 来提供。 >###基于 DbContext 的健康检查 <br/> tn>下面通过简单的示例来介绍如何利用该注册 `DbContextHealth<TContext>` 对象来检查对 `DbContext` 的可用性。该类型所在的 NuGet 包 `Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore` 的依赖。除此之外,我们的演示实例采用的数据库类型为 **SQL Server** ,所以还需要为演示程序添加针对 NuGet 包 `Microsoft.EntityFrameworkCore.SqlServer` 的依赖。在添加了上述两个 NuGet 包的依赖之后,我们定义了如下两个空的 `DbContext` 类型(FooContext 和 BarContext)。 ```csharp public class FooContext:DbContext { public FooContext(DbContextOptions<FooContext> options) : base(options) {} } public class BarContext : DbContext { public BarContext(DbContextOptions<BarContext> options) : base(options) {} } ``` tn>在如下所演示程序中,我们调用 `IServiceCollection` 接口的 `AddDbContext<TDbContext>` 扩展方法注册针对 `Entity Framework Core` 的相关服务,并完成了针对上述两个自定义 `DbContext` 类型的注册。我们为 `FooContext` 和 `BarContext` 分别指出了两个针对 **SQL Server** 的连接字符串,其中前者是有效的,后者是无效的。 ```csharp static void Main(string[] args) { var options = new HealthCheckOptions { ResponseWriter = ReportAsync }; Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .ConfigureServices(svcs => svcs .AddDbContext<FooContext>(options => options.UseSqlServer("<Connection String>")) .AddDbContext<BarContext>(options => options.UseSqlServer("<Connection String>")) .AddHealthChecks() .AddDbContextCheck<FooContext>() .AddDbContextCheck<BarContext>() ) .Configure(app => app.UseHealthChecks("/healthcheck", options))) .Build() .Run(); static Task ReportAsync(Microsoft.AspNetCore.Http.HttpContext content, HealthReport report) { var builder = new StringBuilder(); builder.AppendLine($"Status: {report.Status}"); foreach (var name in report.Entries.Keys) { builder.AppendLine($"{name}:{report.Entries[name].Status}"); } return content.Response.WriteAsync(builder.ToString()); } ``` tn>在调用 `IServiceCollection` 接口的 `AddHealthChecks` 扩展方法得到 `IHealthChecksBuilder` 对象之后,我们针对两个 `DbContext` 类型(FooContent 和 BarContext)调用 `AddDbContextCheck<TContext>` 扩展方法,它们会创建并注册对应的 `DbContextHealthCheck<TContext>` 对象。为了得到针对两个 `DbContext` 类型的健康报告,我们依然在注册 `HealthCheckMiddleware` 中间件时指定了对应的配置选项,并通过指定其 `ResponseWrite` 属性将每个健康检查条目的状态呈现到响应内容中。如果直接利用浏览器发送健康检查请求,就会得到如下的健康报告。由于 `FooContext` 连接的数据库是可用的,所以针对它的状态为 `Healthy`.`BarContext` 采用的连接字符串是无效的,所以它对应的状态为 `UnHealthy` ![](https://img.tnblog.net/arcimg/hb/d3e303a5a4644afca689155f5ec99d07.png) tn>我们基于上一次的序列化完整输出,如下图所示 ![](https://img.tnblog.net/arcimg/hb/709f3db6f63a44b283eb72f346114d86.png) >###发布健康报告 tn>我们通过如下实例来介绍健康报告的定期发布。健康报告的发布是通过 `IHealthCheck Publisher` 服务来完成的。我们实现该接口的实现类型 `ConsolePublisher` 将健康报告输出到控制台上。如下所示的代码片段展示了如何利用 `ConsolePublisher` 对象将收集的健康报告以设定的时间间隔输出到控制台上。 ```csharp var random = new Random(); var options = new HealthCheckOptions { ResponseWriter = ReportAsync }; Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .ConfigureServices(svcs => svcs .AddHealthChecks() .AddCheck("aaa", Check) .AddCheck("bbb", Check) .AddCheck("ccc", Check) .AddConsolePublisher() .ConfigurePublisher(options => options.Period = TimeSpan.FromSeconds(5))) ) .Configure(app => app.UseHealthChecks("/healthcheck", options))) .Build() .Run(); static Task ReportAsync(Microsoft.AspNetCore.Http.HttpContext content, HealthReport report) { content.Response.ContentType = "application/json"; var settings = new JsonSerializerSettings(); settings.Formatting = Formatting.Indented; settings.Converters.Add(new StringEnumConverter()); return content.Response.WriteAsync(JsonConvert.SerializeObject(report, settings)); } HealthCheckResult Check() { return (random.Next(1, 4)) switch { 1 => HealthCheckResult.Unhealthy("Unavailable"), 2 => HealthCheckResult.Degraded("Degraded"), _ => HealthCheckResult.Healthy("Normal") }; } ``` tn>如上代码我们注册了3个 `IHealthCheckBuilder` 对象,它们会随机返回3种状态的健康状态。`ConsolePublisher` 对象的注册体现在针对 `AddConsolePublisher` 方法的调用上,这是专门为 `IHealthCheckBuilder` 接口定义的扩展方法。借助调用 `ConfigurePublisher`方法也是自定义扩展方法,我们利用它将健康报告间隔设置为5秒。 ```csharp public static class Extensions { public static IHealthChecksBuilder AddConsolePublisher(this IHealthChecksBuilder builder) { builder.Services.AddSingleton<IHealthCheckPublisher, ConsolePublisher>(); return builder; } public static IHealthChecksBuilder ConfigurePublisher(this IHealthChecksBuilder builder, Action<HealthCheckPublisherOptions> configure) { builder.Services.Configure(configure); return builder; } } ``` ```csharp public class ConsolePublisher : IHealthCheckPublisher { private readonly ObjectPool<StringBuilder> _stringBuilderPool; public ConsolePublisher(ObjectPoolProvider provider) { _stringBuilderPool = provider.CreateStringBuilderPool(); } public Task PublishAsync(HealthReport report, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var builder = _stringBuilderPool.Get(); try { builder.AppendLine($"Status: {report.Status}[{ DateTimeOffset.Now.ToString("yy-MM-dd hh:mm:ss")}]"); foreach (var name in report.Entries.Keys) { builder.AppendLine($" {name}: {report.Entries[name].Status}"); } Console.WriteLine(builder); return Task.CompletedTask; } finally { _stringBuilderPool.Return(builder); } } } ``` ![](https://img.tnblog.net/arcimg/hb/6f1d827c754f4480b262752d03dcf052.png) 健康检查(UI) ------------ tn>虽然官方为我们提供的运行检查库已经足够轻量和简单。但是为了避免重复造轮子,我们可以使用`AspNetCore.Diagnostics.HealthChecks`包,该项目包含了许多情况的检查,比如 `Sql Server`、`MySql`、`Elasticsearch`、`Redis`、`Kafka`等等。 并且还为我们提供一个UI界面,可供查看,通过 NuGet 包`AspNetCore.HealthChecks.UI.Client`提供客户端独特的输出格式,改动原有代码: ```csharp static void LastPractice() { var random = new Random(); var options = new HealthCheckOptions { Predicate = _ => true, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse//ReportAsync }; var options2 = new HealthCheckOptions { ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, Predicate = reg => reg.Name == "ccc" }; Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(builder => builder .ConfigureServices(svcs => svcs .AddHealthChecks() .AddCheck("aaa", Check) .AddCheck("bbb", Check) .AddCheck("ccc", Check) .AddConsolePublisher() .ConfigurePublisher(option=>option.Period = TimeSpan.FromSeconds(5)) ) .Configure(app => { app.UseHealthChecks("/healthcheck", options); app.UseHealthChecks("/healthcheck2", options2); })) .Build() .Run(); static Task ReportAsync(Microsoft.AspNetCore.Http.HttpContext content, HealthReport report) { content.Response.ContentType = "application/json"; var settings = new JsonSerializerSettings(); settings.Formatting = Formatting.Indented; settings.Converters.Add(new StringEnumConverter()); return content.Response.WriteAsync(JsonConvert.SerializeObject(report, settings)); } HealthCheckResult Check() { return (random.Next(1, 4)) switch { 1 => HealthCheckResult.Unhealthy("Unavailable"), 2 => HealthCheckResult.Degraded("Degraded"), _ => HealthCheckResult.Healthy("Normal") }; } } ``` tn>通过 `IApplicationBuilder` 接口的 `UseHealthChecks` 扩展方法去注册 2 个 `HealthChecksMiddle` 配置不一的中间件,同时也映射出两种不同的路径 `/healthcheck` 与 `/healthcheck2`,前者包括所有注册的服务与插件可以进行健康检查,后者只能检查名为 `ccc` 的服务。 ![](https://img.tnblog.net/arcimg/hb/70ee025b42594667ad3c4c5f5e657542.png) ![](https://img.tnblog.net/arcimg/hb/ee6563ac81784ce89c54fe6fb739ffa9.png) >创建一个项目名为 `HealthDashboard` 的 **webApi** 网站,添加健康面板 `AspNetCore.HealthChecks.UI` 以及 `AspNetCore.HealthChecks.UI.InMemory.Storage` 依赖包。注册 `HealthCheck` 健康面板的相关服务,并映射相关路径,默认通过 `/healthchecks-ui` 即可访问。 ```csharp public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services .AddHealthChecksUI() .AddInMemoryStorage(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app .UseRouting() .UseEndpoints(config => { config.MapHealthChecksUI(); }); } } ``` tn>对 **appsetting.json** 我们也需要对其进行修改。主要是针对 `HealthChecksUI` 的配置,我们从中可以看到 `HealthChecks` 节点下添加了两个检测节点。接下来我们通过浏览器访问 `/healthchecks-ui` 查看二者的连接情况。 ```json { "HealthChecksUI": { "HealthChecks": [ { "Name": "IHealthCheckConsole", "Uri": "http://localhost:5000/healthcheck" }, { "Name": "IHealthCheckConsole-Only-CCC", "Uri": "http://localhost:5000/healthcheck2" } ], "Webhooks": [ { "Name": "Default", "Uri": "", "Payload": "{\"text\":\"The HealthCheck [[LIVENESS]] is failing with the error message: [[FAILURE]]. [[DESCRIPTIONS]]. <http://yourappstatus|Click here> to get more details.\",\"channel\":\"#general\",\"link_names\": 1,\"username\":\"monkey-bot\",\"icon_emoji\":\":monkey_face:\"}", "RestoredPayload": "{\"text\":\"The HealthCheck [[LIVENESS]] is recovered. All is up and running\",\"channel\":\"#general\",\"link_names\": 1,\"username\":\"monkey-bot\",\"icon_emoji\":\":monkey_face:\"}" } ], "EvaluationTimeinSeconds": 10, "MinimumSecondsBetweenFailureNotifications": 60 } } ``` ![](https://img.tnblog.net/arcimg/hb/e642474be5134c4a8d62ef414fe611cd.png) tn>我们从健康检测UI中直关的看到每个注册点下,服务和插件的运行情况。关于 **appsettings.json** 文件中的配置参数可以参考如下。 >###HealthChecks <br/> tn>默认情况下,`HealthChecks` 返回一个简单的状态码(200或503),而不包含 `HealthReport` 数据。如果您希望 `HealthCheck-UI` 显示来自 `HealthCheck` 的 `HealthReport` 数据,则可以启用它以添加特定的 `ResponseWriter`。要在HealthCheck-UI中显示这些HealthCheck,必须通过HealthCheck-UI设置对其进行配置。同时也等同于如下代码: ```csharp public void ConfigureServices(IServiceCollection services) { services .AddHealthChecksUI(setup=> { setup.AddHealthCheckEndpoint("IHealthCheckConsole", "http://localhost:5000/healthcheck"); setup.AddHealthCheckEndpoint("IHealthCheckConsole-Only-CCC", "http://localhost:5000/healthcheck2"); }) .AddInMemoryStorage(); } ``` >###Webhooks <br/> tn>您可以使用IConfiguration提供程序(应用程序设置,用户机密,环境变量)配置这些Healthcheck和Webhooks,也可以使用AddHealthChecksUI(setupSettings:setup =>)方法。具体请参考 <a href="https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/doc/webhooks.md">Webhooks</a> 在这里等同于如下代码: ```csharp public void ConfigureServices(IServiceCollection services) { services .AddHealthChecksUI(setup=> { setup.AddHealthCheckEndpoint("IHealthCheckConsole", "http://localhost:5000/healthcheck"); setup.AddHealthCheckEndpoint("IHealthCheckConsole-Only-CCC", "http://localhost:5000/healthcheck2"); setup.AddWebhookNotification("Default", uri: "", payload: "{...}"); }) .AddInMemoryStorage(); } ``` tn>如果配置了WebHooks部分,则HealthCheck-UI会自动将新通知发布到webhook集合中。HealthCheckUI对webhook的Payload和RestorePayload属性中的值使用简单的替换方法。目前,我们支持两个书签: *[[LIVENESS]] 返回Down的活动的名称。* *[[FAILURE]] 带有失败的详细消息。* *[[DESCRIPTIONS]] 故障描述* **Webhooks可以使用配置提供程序进行配置,也可以通过代码进行配置。使用代码可以进行更大程度的自定义,因为您可以设置自己的用户功能来自定义输出消息或配置是否将有效负载发送到给定的Webhook端点。** >###EvaluationTimeinSeconds tn>运行状况检查之间经过的秒数。 >###MinimumSecondsBetweenFailureNotifications tn>故障通知之间的最小秒数,以避免接收器满溢。 >### UI自定义样式表 tn>UI通过使用自定义样式表和css变量支持自定义样式和品牌。要添加自定义样式表,请使用UI设置方法 <br/> >添加示例文件以及样式 ![](https://img.tnblog.net/arcimg/hb/f73bd80ebef14d8faf21b94e0ad517d2.png) >dotnet.css 样式如下 ```css :root { --primaryColor: #68217a; --secondaryColor: #f4f4f4; --bgMenuActive: #8e47a0; --bgButton: #68217a; --logoImageUrl: url('../../logo.png'); --bgAside: var(--primaryColor); } ``` >Startup.cs ```css public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseStaticFiles(); app .UseRouting() .UseEndpoints(config => { config.MapHealthChecksUI(setup=> { setup.AddCustomStylesheet("wwwroot\\dotnet.css"); }); }); } ``` ![](https://img.tnblog.net/arcimg/hb/6172ff2627b5419dbab2504bcb046fac.png) tn>更多请参考:https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/doc/styles-branding.md HealthCheck 与 Kubernetes ------------ https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/doc/k8s-operator.md