ASP.NET Core中的运行状况检查

由卢克·莱瑟姆和格伦Condron

ASP.NET Core提供了运行状况检查中间件和库,用于报告应用程序基础结构组件的运行状况。

运行状况检查由应用程序公开为HTTP终结点。可以为各种实时监视方案配置运行状况检查端点:

容器协调程序和负载平衡器可以使用运行状况探针来检查应用程序的状态。例如,容器协调器可以通过停止滚动部署或重新启动容器来响应运行状况检查失败。负载平衡器可能会通过将流量从发生故障的实例路由到运行状况良好的实例来对运行状况不佳的应用程序做出反应。
可以监视内存,磁盘和其他物理服务器资源的使用情况,以确保运行状况良好。
运行状况检查可以测试应用程序的依赖项(例如数据库和外部服务端点),以确认可用性和正常功能。
查看或下载示例代码(如何下载)

该示例应用程序包括本主题中描述的方案的示例。要在给定场景下运行示例应用程序,请在命令外壳中使用项目文件夹中的dotnet run命令。请参阅示例应用程序的README.md文件和本主题中的方案说明,以获取有关如何使用示例应用程序的详细信息。

先决条件
健康检查通常与外部监视服务或容器协调程序一起使用,以检查应用程序的状态。在向应用程序添加运行状况检查之前,请确定要使用的监视系统。监视系统指示要创建的健康检查类型以及如何配置其终结点。

引用Microsoft.AspNetCore.App元包,或将包引用添加到Microsoft.AspNetCore.Diagnostics.HealthChecks包。

该示例应用程序提供了启动代码,以演示几种情况下的运行状况检查。该数据库探测情况检查使用数据库连接的健康AspNetCore.Diagnostics.HealthChecks。该的DbContext探头场景检查使用EF核心数据库DbContext。要探索数据库方案,示例应用程序:

创建一个数据库,并在appsettings.json文件中提供其连接字符串。
在其项目文件中具有以下程序包引用:
AspNetCore.HealthChecks.SqlServer
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
注意

Microsoft不维护或不支持AspNetCore.Diagnostics.HealthChecks。

另一个运行状况检查方案演示了如何将运行状况检查过滤到管理端口。该示例应用程序要求您创建一个包含管理URL和管理端口的Properties / launchSettings.json文件。有关更多信息,请参见按端口过滤部分。

基本健康探针
对于许多应用程序而言,报告应用程序是否可处理请求(活动)的基本运行状况探测器配置足以发现应用程序的状态。

基本配置注册运行状况检查服务,并调用运行状况检查中间件以在URL终结点响应并带有运行状况响应。默认情况下,没有注册特定的运行状况检查来测试任何特定的依赖项或子系统。如果该应用能够在运行状况端点URL上响应,则该应用程序被视为运行状况良好。默认响应编写器将状态(HealthStatus)作为纯文本响应写回到客户端,指示HealthStatus.Healthy,HealthStatus.Degraded或HealthStatus.Unhealthy状态。

在中使用AddHealthChecks注册运行状况检查服务Startup.ConfigureServices。在的请求处理管道中使用UseHealthChecks添加用于Health Checks中间件的端点Startup.Configure。

在示例应用程序中,运行状况检查端点在/health(BasicStartup.cs)中创建:

C#

复制
public class BasicStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}

public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/health");
}
}
要使用示例应用程序运行基本配置方案,请在命令外壳程序的项目文件夹中执行以下命令:

.NET Core CLI

复制
dotnet run --scenario basic
Docker范例
Docker提供了一个内置HEALTHCHECK指令,可用于检查使用基本运行状况检查配置的应用程序的状态:


复制
HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit
创建健康检查
通过实现IHealthCheck接口来创建运行状况检查。该CheckHealthAsync方法返回一个HealthCheckResult指示健康Healthy,Degraded或Unhealthy。结果以带有可配置状态代码的纯文本响应形式写入(“运行状况检查选项”部分中描述了配置)。HealthCheckResult还可以返回可选的键值对。

健康检查示例
以下ExampleHealthCheck课程演示了健康检查的布局。健康检查逻辑放置在CheckHealthAsync方法中。以下示例将虚拟变量设置healthCheckResultHealthy为true。如果将的值healthCheckResultHealthy设置为false,则返回HealthCheckResult.Unhealthy状态。

C#

复制
public class ExampleHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var healthCheckResultHealthy = true;

if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("The check indicates a healthy result."));
}

return Task.FromResult(
HealthCheckResult.Unhealthy("The check indicates an unhealthy result."));
}
}
注册健康检查服务
该ExampleHealthCheck类型Startup.ConfigureServices通过AddCheck添加到运行状况检查服务中:

C#

复制
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
以下示例中显示的AddCheck重载将故障状态(HealthStatus)设置为在运行状况检查报告失败时报告。如果故障状态设置为null(默认),则报告HealthStatus.Unhealthy。对于库作者而言,此重载是一个有用的方案,如果运行状况检查实现接受该设置,则当运行状况检查失败时,应用程序会强制执行库指示库指示的故障状态。

标签可用于过滤运行状况检查(在“ 过滤运行状况检查”部分中进一步介绍)。

C#

复制
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>(
"example_health_check",
failureStatus: HealthStatus.Degraded,
tags: new[] { "example" });
AddCheck也可以执行lambda函数。在以下Startup.ConfigureServices示例中,运行状况检查名称指定为,Example并且该检查始终返回状况良好的状态:

C#

复制
services.AddHealthChecks()
.AddCheck("Example", () =>
HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });
使用运行状况检查中间件
在中Startup.Configure,使用端点URL或相对路径在处理管道中调用UseHealthChecks:

C#

复制
app.UseHealthChecks("/health");
如果运行状况检查应侦听特定端口,请使用UseHealthChecks的重载来设置端口(在“ 按端口过滤”部分中进一步描述):

C#

复制
app.UseHealthChecks("/health", port: 8000);
健康检查选项
HealthCheckOptions提供了自定义健康检查行为的机会:

筛选健康检查
自定义HTTP状态代码
禁止缓存头
自定义输出
筛选健康检查
默认情况下,运行状况检查中间件运行所有已注册的运行状况检查。要运行运行状况检查的子集,请提供一个将布尔值返回到谓词选项的函数。在以下示例中,Bar运行状况检查将通过其bar_tag在函数的条件语句中的标记()过滤掉,true仅在运行状况检查的Tags属性与foo_tag或匹配时才返回baz_tag:

C#

复制
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddCheck("Foo", () =>
HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
.AddCheck("Bar", () =>
HealthCheckResult.Unhealthy("Bar is unhealthy!"),
tags: new[] { "bar_tag" })
.AddCheck("Baz", () =>
HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });
}

public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/health", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("foo_tag") ||
check.Tags.Contains("baz_tag")
});
}
自定义HTTP状态代码
使用ResultStatusCodes可以自定义健康状态到HTTP状态代码的映射。以下StatusCodes分配是中间件使用的默认值。更改状态代码值以满足您的要求。

在Startup.Configure:

C#

复制
//using Microsoft.AspNetCore.Diagnostics.HealthChecks;
//using Microsoft.Extensions.Diagnostics.HealthChecks;

app.UseHealthChecks("/health", new HealthCheckOptions()
{
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status200OK,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
}
});
禁止缓存头
AllowCachingResponses控制运行状况检查中间件是否将HTTP标头添加到探测响应中以防止响应缓存。如果该值是false(默认值),中间件集合或替代的Cache-Control,Expires和Pragma插座,以避免响应缓存。如果值为true,则中间件不会修改响应的缓存头。

在Startup.Configure:

C#

复制
//using Microsoft.AspNetCore.Diagnostics.HealthChecks;
//using Microsoft.Extensions.Diagnostics.HealthChecks;

app.UseHealthChecks("/health", new HealthCheckOptions()
{
AllowCachingResponses = false
});
自定义输出
该ResponseWriter选项获取或设置用来写响应的委托。默认委托使用HealthReport.Status字符串值编写一个最小的纯文本响应。

在Startup.Configure:

C#

复制
// using Microsoft.AspNetCore.Diagnostics.HealthChecks;
// using Microsoft.Extensions.Diagnostics.HealthChecks;

app.UseHealthChecks("/health", new HealthCheckOptions()
{
ResponseWriter = WriteResponse
});
默认委托使用HealthReport.Status字符串值编写一个最小的纯文本响应。以下定制委托,WriteResponse输出定制JSON响应:

C#

复制
private static Task WriteResponse(HttpContext httpContext, HealthReport result)
{
httpContext.Response.ContentType = "application/json";

var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
return httpContext.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
健康状况检查系统不为复杂的JSON返回格式提供内置支持,因为该格式特定于您选择的监视系统。可以根据JObject需要随意自定义前面的示例中的。

数据库探针
运行状况检查可以指定要作为布尔测试运行的数据库查询,以指示数据库是否正常响应。

该示例应用程序使用AspNetCore.Diagnostics.HealthChecks(用于ASP.NET Core应用程序的运行状况检查库)对SQL Server数据库执行运行状况检查。对数据库AspNetCore.Diagnostics.HealthChecks执行SELECT 1查询,以确认到数据库的连接正常。

警告

使用查询检查数据库连接时,请选择一个快速返回的查询。查询方法冒着数据库过载和性能下降的风险。在大多数情况下,不需要运行测试查询。仅成功建立与数据库的连接就足够了。如果发现有必要运行查询,请选择一个简单的SELECT查询,例如SELECT 1。

包括对AspNetCore.HealthChecks.SqlServer的程序包引用。

在示例应用程序的appsettings.json文件中提供有效的数据库连接字符串。该应用程序使用一个名为的SQL Server数据库HealthCheckSample:

JSON格式

复制
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
},
"Logging": {
"LogLevel": {
"Default": "Debug"
},
"Console": {
"IncludeScopes": "true"
}
}
}
在中使用AddHealthChecks注册运行状况检查服务Startup.ConfigureServices。该示例应用程序AddSqlServer使用数据库的连接字符串(DbHealthStartup.cs)调用该方法:

C#

复制
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
}
在以下应用程序处理管道中调用Health Checks Middleware Startup.Configure:

C#

复制
app.UseHealthChecks("/health");
要使用示例应用程序运行数据库探测方案,请在命令外壳程序的项目文件夹中执行以下命令:

.NET Core CLI

复制
dotnet run --scenario db
注意

Microsoft不维护或不支持AspNetCore.Diagnostics.HealthChecks。

实体框架核心DbContext探针
该DbContext检查确认该应用程序可以与为EF Core配置的数据库进行通信DbContext。该DbContext检查支持的应用程序是:

使用实体框架(EF)核心。
包括对Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore的包引用。
AddDbContextCheck<TContext>为进行健康检查DbContext。将DbContext作为TContext方法提供。重载可用于配置故障状态,标签和自定义测试查询。

默认:

该DbContextHealthCheck调用EF核心的CanConnectAsync方法。您可以自定义使用AddDbContextCheck方法重载检查运行状况时运行的操作。
健康检查的名称就是TContext类型的名称。
在示例应用程序中,AppDbContext将其提供给(DbContextHealthStartup.cs)AddDbContextCheck并注册为服务:Startup.ConfigureServices

C#

复制
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
Configuration["ConnectionStrings:DefaultConnection"]);
});
}
在示例应用程序中,在中UseHealthChecks添加“运行状况检查中间件” Startup.Configure。

C#

复制
app.UseHealthChecks("/health");
要DbContext使用示例应用程序运行探测方案,请确认SQL Server实例中不存在由连接字符串指定的数据库。如果数据库存在,请将其删除。

在命令外壳程序的项目文件夹中执行以下命令:

.NET Core CLI

复制
dotnet run --scenario dbcontext
应用程序运行后,通过/health在浏览器中向端点发出请求来检查运行状况。该数据库AppDbContext不存在,因此应用程序提供以下响应:


复制
Unhealthy
触发示例应用程序以创建数据库。向发出请求/createdatabase。该应用程序响应:


复制
Creating the database...
Done!
Navigate to /health to see the health status.
向/health端点发出请求。数据库和上下文存在,因此应用程序响应:


复制
Healthy
触发示例应用程序以删除数据库。向发出请求/deletedatabase。该应用程序响应:


复制
Deleting the database...
Done!
Navigate to /health to see the health status.
向/health端点发出请求。该应用程序提供了不健康的响应:


复制
Unhealthy
单独的就绪和活跃性探针
在某些托管方案中,会使用一对运行状况检查来区分两个应用程序状态:

该应用程序正在运行,但尚未准备好接收请求。此状态是应用程序的就绪状态。
该应用程序正在运行并正在响应请求。此状态是应用程序的活动状态。
准备情况检查通常执行一组更广泛且耗时的检查,以确定应用程序的所有子系统和资源是否可用。活动检查仅执行快速检查,以确定该应用是否可用于处理请求。应用程序通过就绪检查后,无需再为昂贵的就绪检查集增加负担,进一步的检查仅需要检查活动性即可。

该示例应用程序包含运行状况检查,以报告托管服务中长时间运行的启动任务的完成。该StartupHostedServiceHealthCheck属性,自曝StartupTaskCompleted,该托管服务可以设置为true当其长时间运行的任务完成(StartupHostedServiceHealthCheck.cs):

C#

复制
public class StartupHostedServiceHealthCheck : IHealthCheck
{
private volatile bool _startupTaskCompleted = false;

public string Name => "slow_dependency_check";

public bool StartupTaskCompleted
{
get => _startupTaskCompleted;
set => _startupTaskCompleted = value;
}

public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
if (StartupTaskCompleted)
{
return Task.FromResult(
HealthCheckResult.Healthy("The startup task is finished."));
}

return Task.FromResult(
HealthCheckResult.Unhealthy("The startup task is still running."));
}
}
长时间运行的后台任务由托管服务(Services / StartupHostedService)启动。在任务结束时,StartupHostedServiceHealthCheck.StartupTaskCompleted设置为true:

C#

复制
public class StartupHostedService : IHostedService, IDisposable
{
private readonly int _delaySeconds = 15;
private readonly ILogger _logger;
private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

public StartupHostedService(ILogger<StartupHostedService> logger,
StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
{
_logger = logger;
_startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
}

public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is starting.");

// Simulate the effect of a long-running startup task.
Task.Run(async () =>
{
await Task.Delay(_delaySeconds * 1000);

_startupHostedServiceHealthCheck.StartupTaskCompleted = true;

_logger.LogInformation("Startup Background Service has started.");
});

return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Startup Background Service is stopping.");

return Task.CompletedTask;
}

public void Dispose()
{
}
}
运行状况检查与托管服务一起在AddCheck中注册Startup.ConfigureServices。因为托管服务必须在运行状况检查中设置属性,所以运行状况检查也已在服务容器(LivenessProbeStartup.cs)中注册:

C#

复制
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});

// The following workaround permits adding an IHealthCheckPublisher
// instance to the service container when one or more other hosted
// services have already been added to the app. This workaround
// won't be required with the release of ASP.NET Core 3.0. For more
// information, see: https://github.com/aspnet/Extensions/issues/639.
services.TryAddEnumerable(
ServiceDescriptor.Singleton(typeof(IHostedService),
typeof(HealthCheckPublisherOptions).Assembly
.GetType(HealthCheckServiceAssembly)));

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
}
在中的应用程序处理管道中调用Health Checks Middleware Startup.Configure。在示例应用程序中,将在处创建运行状况检查端点,以/health/ready进行准备情况检查和/health/live活动检查。就绪检查将健康检查过滤为带有ready标签的健康检查。该真人判断滤掉StartupHostedServiceHealthCheck通过返回false的HealthCheckOptions.Predicate(有关详细信息,请参阅筛选健康检查):

C#

复制
app.UseHealthChecks("/health/ready", new HealthCheckOptions()
{
Predicate = (check) => check.Tags.Contains("ready"),
});

app.UseHealthChecks("/health/live", new HealthCheckOptions()
{
Predicate = (_) => false
});
要使用示例应用程序运行就绪/活跃性配置方案,请在命令外壳中的项目文件夹中执行以下命令:

.NET Core CLI

复制
dotnet run --scenario liveness
在浏览器中,访问/health/ready几次直到15秒过去。运行状况检查在前15秒钟报告不健康。15秒后,端点报告“ 健康”,这反映了托管服务已完成长时间运行的任务。

此示例还创建了运行状况检查发布者(IHealthCheckPublisher实现),该运行情况以两秒的延迟运行了第一次就绪检查。有关更多信息,请参见运行状况检查发布者部分。

Kubernetes示例
在诸如Kubernetes之类的环境中,使用单独的准备情况和活动检查很有用。在Kubernetes中,可能需要一个应用程序在接受请求之前执行耗时的启动工作,例如测试基础数据库可用性。使用单独的检查,协调器可以区分应用程序是否正在运行但尚未准备就绪,或者应用程序无法启动。有关Kubernetes中的就绪和活跃性探针的更多信息,请参阅Kubernetes文档中的配置活跃性和就绪性探针。

以下示例演示了Kubernetes准备就绪探针配置:


复制
spec:
template:
spec:
readinessProbe:
# an http probe
httpGet:
path: /health/ready
port: 80
# length of time to wait for a pod to initialize
# after pod startup, before applying health checking
initialDelaySeconds: 30
timeoutSeconds: 1
ports:
- containerPort: 80
具有自定义响应编写器的基于度量的探针
该示例应用程序使用自定义响应编写器演示了内存运行状况检查。

MemoryHealthCheck如果应用程序使用了超过给定的内存阈值(示例应用程序中为1 GB),则会报告不健康状态。该HealthCheckResult包括用于该应用(垃圾收集器(GC)信息MemoryHealthCheck.cs):

C#

复制
public class MemoryHealthCheck : IHealthCheck
{
private readonly IOptionsMonitor<MemoryCheckOptions> _options;

public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
{
_options = options;
}

public string Name => "memory_check";

public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
var options = _options.Get(context.Registration.Name);

// Include GC information in the reported diagnostics.
var allocated = GC.GetTotalMemory(forceFullCollection: false);
var data = new Dictionary<string, object>()
{
{ "AllocatedBytes", allocated },
{ "Gen0Collections", GC.CollectionCount(0) },
{ "Gen1Collections", GC.CollectionCount(1) },
{ "Gen2Collections", GC.CollectionCount(2) },
};

var status = (allocated < options.Threshold) ?
HealthStatus.Healthy : HealthStatus.Unhealthy;

return Task.FromResult(new HealthCheckResult(
status,
description: "Reports degraded status if allocated bytes " +
$">= {options.Threshold} bytes.",
exception: null,
data: data));
}
}
在中使用AddHealthChecks注册运行状况检查服务Startup.ConfigureServices。相反,通过它传递给启用健康检查的AddCheck中,MemoryHealthCheck被注册为服务。所有IHealthCheck注册的服务都可用于健康检查服务和中间件。我们建议将运行状况检查服务注册为Singleton服务。

在示例应用程序(CustomWriterStartup.cs)中:

C#

复制
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddMemoryHealthCheck("memory");
}
在中的应用程序处理管道中调用Health Checks Middleware Startup.Configure。在运行状况检查执行时,将为属性WriteResponse提供一个委托ResponseWriter以输出自定义JSON响应:

C#

复制
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/health", new HealthCheckOptions()
{
// This custom writer formats the detailed status as JSON.
ResponseWriter = WriteResponse
});
}
该WriteResponse方法将格式化CompositeHealthCheckResult为JSON对象,并为运行状况检查响应生成JSON输出:

C#

复制
private static Task WriteResponse(HttpContext httpContext,
HealthReport result)
{
httpContext.Response.ContentType = "application/json";

var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
return httpContext.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
要使用示例应用程序运行带有自定义响应编写器输出的基于度量的探针,请在命令外壳程序的项目文件夹中执行以下命令:

.NET Core CLI

复制
dotnet run --scenario writer
注意

AspNetCore.Diagnostics.HealthChecks包括基于指标的运行状况检查方案,包括磁盘存储和最大值活动检查。

Microsoft不维护或不支持AspNetCore.Diagnostics.HealthChecks。

按端口过滤
通过端口调用UseHealthChecks会将运行状况检查请求限制为指定的端口。通常在容器环境中使用它来公开用于监视服务的端口。

该示例应用程序使用环境变量配置提供程序配置端口。该端口在launchSettings.json文件中设置,并通过环境变量传递给配置提供程序。您还必须配置服务器以侦听管理端口上的请求。

要使用示例应用程序演示管理端口配置,请在Properties文件夹中创建launchSettings.json文件。

示例应用程序中的以下Properties / launchSettings.json文件未包含在示例应用程序的项目文件中,必须手动创建:

JSON格式

复制
{
"profiles": {
"SampleApp": {
"commandName": "Project",
"commandLineArgs": "",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
"ASPNETCORE_MANAGEMENTPORT": "5001"
},
"applicationUrl": "http://localhost:5000/"
}
}
}
在中使用AddHealthChecks注册运行状况检查服务Startup.ConfigureServices。对UseHealthChecks的调用指定了管理端口(ManagementPortStartup.cs):

C#

复制
public class ManagementPortStartup
{
public ManagementPortStartup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/health", port: Configuration["ManagementPort"]);

app.Run(async (context) =>
{
await context.Response.WriteAsync(
"Navigate to " +
$"http://localhost:{Configuration["ManagementPort"]}/health " +
"to see the health status.");
});
}
}
注意

您可以通过在代码中显式设置URL和管理端口来避免在示例应用程序中创建launchSettings.json文件。在创建WebHostBuilder的Program.cs中,添加对UseUrls的调用,并提供应用程序的常规响应终结点和管理端口终结点。在其中调用UseHealthChecks的ManagementPortStartup.cs中,显式指定管理端口。

Program.cs:

C#

复制
return new WebHostBuilder()
.UseConfiguration(config)
.UseUrls("http://localhost:5000/;http://localhost:5001/")
.ConfigureLogging(builder =>
{
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConfiguration(config);
builder.AddConsole();
})
.UseKestrel()
.UseStartup(startupType)
.Build();
ManagementPortStartup.cs:

C#

复制
app.UseHealthChecks("/health", port: 5001);
要使用示例应用程序运行管理端口配置方案,请在命令外壳程序的项目文件夹中执行以下命令:

.NET Core CLI

复制
dotnet run --scenario port
分发健康检查库
要将健康检查作为库分发:

编写将IHealthCheck接口实现为独立类的运行状况检查。该类可以依赖于依赖项注入(DI),类型激活和命名选项来访问配置数据。

在运行状况检查逻辑中CheckHealthAsync:

data1并且data2在运行探头的健康检查逻辑的方法被使用。
AccessViolationException 被处理。
当AccessViolationException发生时,FailureStatus与返回HealthCheckResult允许用户配置健康检查故障状态。

C#

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

public class ExampleHealthCheck : IHealthCheck
{
private readonly string _data1;
private readonly int? _data2;

public ExampleHealthCheck(string data1, int? data2)
{
_data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
_data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
}

public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context, CancellationToken cancellationToken)
{
try
{
return HealthCheckResult.Healthy();
}
catch (AccessViolationException ex)
{
return new HealthCheckResult(
context.Registration.FailureStatus,
description: "An access violation occurred during the check.",
exception: ex,
data: null);
}
}
}
编写一个扩展方法,其中包含使用方应用程序在其Startup.Configure方法中调用的参数。在以下示例中,假定以下运行状况检查方法签名:

C#

复制
ExampleHealthCheck(string, string, int )
前面的签名表示ExampleHealthCheck需要额外的数据来处理运行状况检查探针逻辑。使用扩展方法注册运行状况检查时,会将数据提供给用于创建运行状况检查实例的委托。在以下示例中,调用方指定了可选的:

健康检查名称(name)。如果null,example_health_check被使用。
健康检查(data1)的字符串数据点。
健康检查(data2)的整数数据点。如果null,1被使用。
故障状态(HealthStatus)。默认值为null。如果为null,则报告失败状态为HealthStatus.Unhealthy。
标签(IEnumerable<string>)。
C#

复制
using System.Collections.Generic;
using Microsoft.Extensions.Diagnostics.HealthChecks;

public static class ExampleHealthCheckBuilderExtensions
{
const string DefaultName = "example_health_check";

public static IHealthChecksBuilder AddExampleHealthCheck(
this IHealthChecksBuilder builder,
string name = default,
string data1,
int data2 = 1,
HealthStatus? failureStatus = default,
IEnumerable<string> tags = default)
{
return builder.Add(new HealthCheckRegistration(
name ?? DefaultName,
sp => new ExampleHealthCheck(data1, data2),
failureStatus,
tags));
}
}
健康检查发布者
将IHealthCheckPublisher添加到服务容器后,运行状况检查系统会定期执行您的运行状况检查并调用PublishAsync结果。这在基于推送的运行状况监视系统方案中很有用,该方案要求每个进程定期调用监视系统以确定运行状况。

所述IHealthCheckPublisher接口有一个方法:

C#

复制
Task PublishAsync(HealthReport report, CancellationToken cancellationToken);
HealthCheckPublisherOptions允许您设置:

延迟 –应用程序启动后在执行IHealthCheckPublisher实例之前应用的初始延迟。延迟在启动时应用一次,不适用于后续迭代。默认值为五秒钟。
时间段– IHealthCheckPublisher执行的时间段。默认值为30秒。
断言 -如果断言是null(默认),健康检查服务出版商运行所有登记的医疗检查。要运行运行状况检查的子集,请提供一个过滤检查集的功能。该谓词在每个期间都会进行评估。
超时 –对所有IHealthCheckPublisher实例执行运行状况检查的超时。使用InfiniteTimeSpan可以执行而不会超时。默认值为30秒。
警告

在ASP.NET Core 2.2发行版中,IHealthCheckPublisher实现不支持设置Period。它设置Delay的值。此问题已在ASP.NET Core 3.0中解决。

在示例应用程序中,ReadinessPublisher是IHealthCheckPublisher实现。将为每个检查记录运行状况检查状态,如下所示:

健康检查状态为“ 健康”的信息(LogInformation)。
如果状态为“ 已降级”或“ 不正常”,则显示错误(LogError)。
C#

复制
public class ReadinessPublisher : IHealthCheckPublisher
{
private readonly ILogger _logger;

public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
{
_logger = logger;
}

// The following example is for demonstration purposes only. Health Checks
// Middleware already logs health checks results. A real-world readiness
// check in a production app might perform a set of more expensive or
// time-consuming checks to determine if other resources are responding
// properly.
public Task PublishAsync(HealthReport report,
CancellationToken cancellationToken)
{
if (report.Status == HealthStatus.Healthy)
{
_logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}
else
{
_logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
DateTime.UtcNow, report.Status);
}

cancellationToken.ThrowIfCancellationRequested();

return Task.CompletedTask;
}
}
在示例应用程序的LivenessProbeStartup示例中,StartupHostedService就绪检查具有两秒钟的启动延迟,并且每30秒运行一次检查。为了激活IHealthCheckPublisher实现,该示例ReadinessPublisher在依赖项注入(DI)容器中注册为单例服务:

C#

复制
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
.AddCheck<StartupHostedServiceHealthCheck>(
"hosted_service_startup",
failureStatus: HealthStatus.Degraded,
tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(2);
options.Predicate = (check) => check.Tags.Contains("ready");
});

// The following workaround permits adding an IHealthCheckPublisher
// instance to the service container when one or more other hosted
// services have already been added to the app. This workaround
// won't be required with the release of ASP.NET Core 3.0. For more
// information, see: https://github.com/aspnet/Extensions/issues/639.
services.TryAddEnumerable(
ServiceDescriptor.Singleton(typeof(IHostedService),
typeof(HealthCheckPublisherOptions).Assembly
.GetType(HealthCheckServiceAssembly)));

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();
}
注意

以下解决方法允许在将一个或多个其他托管服务添加到应用程序后,将IHealthCheckPublisher实例添加到服务容器。ASP.NET Core 3.0不需要此解决方法。

C#

复制
private const string HealthCheckServiceAssembly =
"Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckPublisherHostedService";

services.TryAddEnumerable(
ServiceDescriptor.Singleton(typeof(IHostedService),
typeof(HealthCheckPublisherOptions).Assembly
.GetType(HealthCheckServiceAssembly)));
注意

AspNetCore.Diagnostics.HealthChecks包括多个系统的发布者,包括Application Insights。

Microsoft不维护或不支持AspNetCore.Diagnostics.HealthChecks。

使用MapWhen限制运行状况检查
使用MapWhen可以有条件地为健康检查端点分支请求管道。

在以下示例中,MapWhen如果收到针对api/HealthCheck端点的GET请求,则分支请求管道以激活“运行状况检查中间件” :

C#

复制
app.MapWhen(
context => context.Request.Method == HttpMethod.Get.Method &&
context.Request.Path.StartsWith("/api/HealthCheck"),
builder => builder.UseHealthChecks());

app.UseMvc();
有关更多信息,请参见ASP.NET Core中间件。

猜你喜欢

转载自www.cnblogs.com/lyl6796910/p/11970949.html