是否有可能在应用程序通过 http 请求启动后配置 aspnet 核心中的健康检查。我目前浏览的所有文档和示例仅在
Startup.cs Configure method
中配置健康检查。
例如,我想定义一个控制器
HealthChecksController
,它具有通过外部应用程序在我的应用程序中添加删除健康检查的操作方法。
public class HealthChecksController : Controller
{
[HttpPost]
public Customer CreateHealthCheck(HealthCheck healthCheck)
{
//Add to existing health checks
}
[HttpDelete]
public void DeleteHealthCheck(int id)
{
//Remove from existing health checks
}
}
我问这个问题的原因是我想开发一个监控系统来检查我的服务器上运行的某些服务的状态,现有的健康检查框架看起来很适合我的要求,而不是重新发明轮子。要监控的服务在应用程序开发阶段是未知的,必须在应用程序部署后进行配置。因此需要在 asp.net 应用程序运行时配置它们。
这甚至可以通过现有的健康检查来实现吗?如果不行,还有其他可行的解决方案吗?
你看过健康检查文档
您如何检查动态服务的状态?我假设它们是 API(为简单起见)
一个解决方案可能是创建一个服务来存储 URL 以检查健康状态:
注意:此示例不包含错误检查或并发保护。
public class HealthCheckService
{
private readonly List<string> _urls = new List<string>();
public void Add(string url)
{
_urls.Add(url);
}
public void Remove(string url)
{
_urls.Remove(url);
}
public IEnumerable<string> GetServices()
{
return _urls;
}
}
在您的启动中将其注册为单例。
services.AddSingleton<HealthCheckService>();
您可以将其注入您的控制器并添加 URL
[ApiController]
[Route("/api/health")]
public class HealthCheckController : ControllerBase
{
private readonly HealthCheckService _service;
public HealthCheckController(HealthCheckService service)
{
_service = service;
}
[HttpPost]
public IActionResult Add(string url)
{
_service.Add(url);
return Ok();
}
[HttpDelete]
public IActionResult Remove(string url)
{
_service.Remove(url);
return Ok();
}
}
然后你需要创建一个继承自
IHealthCheck
的类
public class MyHealthChecks : IHealthCheck
{
private readonly HealthCheckService _service;
public MyHealthChecks(HealthCheckService service)
{
_service = service;
}
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
foreach(var svc in _service.GetServices())
{
// call the URL to verify?
// var response = await httpClient.SendAsync(url);
//
// do something with response and store it in results[svc]
// if (!response.IsSuccessStatusCode)
// {
// return Task.FromResult(new HealthCheckResult(
// HealthStatus.Unhealthy, svc));
// }
}
return Task.FromResult(new HealthCheckResult(
HealthStatus.Healthy));
}
}
您需要修改
CheckHealthAsync
中的代码以调用您的服务并做出适当的响应。
最后在启动时注册健康检查类:
services.AddHealthChecks()
.AddCheck<MyHealthChecks>("CustomHealthChecks");
如果您想返回更详细的健康状况信息,您可以添加自定义回复作者
有点晚了,但是是的,你可以。
首先你需要实现一个自定义的
IHealthCheck
因为默认的是内部密封的。
您可以从 .net 来源克隆
DelegateHealthCheck
:
internal sealed class CustomDelegateHealthCheck : IHealthCheck
{
private readonly Func<CancellationToken, Task<HealthCheckResult>> _check;
/// <summary>
/// Create an instance of <see cref="DelegateHealthCheck"/> from the specified delegate.
/// </summary>
/// <param name="check">A delegate which provides the code to execute when the health check is run.</param>
public CustomDelegateHealthCheck(Func<CancellationToken, Task<HealthCheckResult>> check)
{
_check = check ?? throw new ArgumentNullException(nameof(check));
}
/// <summary>
/// Runs the health check, returning the status of the component being checked.
/// </summary>
/// <param name="context">A context object associated with the current execution.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the health check.</param>
/// <returns>A <see cref="Task{HealthCheckResult}"/> that completes when the health check has finished, yielding the status of the component being checked.</returns>
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) => _check(cancellationToken);
}
然后你可以在运行时像这样添加健康检查:
// get HealthCheckServiceOptions, we need this to access the Registrations
var o = _service.GetRequiredService< IOptions<HealthCheckServiceOptions> >();
// define your health check
var healthCheck = new CustomDelegateHealthCheck((ct) => Task.FromResult(HealthCheckResult.Healthy()));
// append your health check to the Registrations
o.Value.Registrations.Add(new HealthCheckRegistration($"name", healthCheck, failureStatus: null, default, default));