正在执行健康检查.NET核心工作程序服务



如何在中实现健康检查。NET核心工作程序服务?

该服务将在Docker中运行,并且需要能够检查服务的运行状况。

另一种实现方法是实现IHealthCheckPublisher

这种方法的好处是能够重用现有的IHealthCheck,或者与依赖IHealthCheck接口的第三方库集成(如本例(。

尽管您仍然将Microsoft.NET.Sdk.Web作为SDK,但您不需要添加任何asp.net细节。

这里有一个例子:

public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services
.AddHealthChecks()
.AddCheck<RedisHealthCheck>("redis_health_check")
.AddCheck<RfaHealthCheck>("rfa_health_check");
services.AddSingleton<IHealthCheckPublisher, HealthCheckPublisher>();
services.Configure<HealthCheckPublisherOptions>(options =>
{
options.Delay = TimeSpan.FromSeconds(5);
options.Period = TimeSpan.FromSeconds(5);
});
});
}
public class HealthCheckPublisher : IHealthCheckPublisher
{
private readonly string _fileName;
private HealthStatus _prevStatus = HealthStatus.Unhealthy;
public HealthCheckPublisher()
{
_fileName = Environment.GetEnvironmentVariable(EnvVariableNames.DOCKER_HEALTHCHECK_FILEPATH) ??
Path.GetTempFileName();
}
public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
{
// AWS will check if the file exists inside of the container with the command
// test -f $DOCKER_HEALTH_CHECK_FILEPATH
var fileExists = _prevStatus == HealthStatus.Healthy;
if (report.Status == HealthStatus.Healthy)
{
if (!fileExists)
{
using var _ = File.Create(_fileName);
}
}
else if (fileExists)
{
File.Delete(_fileName);
}
_prevStatus = report.Status;
return Task.CompletedTask;
}
}

我认为将SDK更改为Microsoft是不值得的。NET。Sdk。Web。仅仅因为一次健康检查,你就会包含额外的中间件吗?不,谢谢。。。

您可以使用不同的协议,如TCP。

总体思路是:

  1. 创建一个单独的后台服务来创建TCP服务器(查看TcpListener.cs(
  2. 当您收到请求时,您有两个选项:如果应用程序正常,则接受TCP连接,否则拒绝它
  3. 如果你使用容器,你的编排器应该有一个通过TCP调用它的选项(在k8s中有一个属性tcpSocket(

如果您需要更多详细信息,可以查看:监控ASP的运行状况。NET核心后台服务与Kubernetes 上的TCP探测器

干杯!

添加HTTPListener并公开健康检查端点。

使用HTTPListener不需要添加Microsoft。NET。Sdk。Web SDK。

程序.cs

using Consumer;

IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
services.AddHostedService<HttpHealthcheck>();
})
.Build();

await host.RunAsync();

HttpHealthcheck.cs

using System.Net;
using System.Text;

namespace Consumer;

public class HttpHealthcheck : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly HttpListener _httpListener;
private readonly IConfiguration _configuration;


public HealthcheckHttpListener(ILogger<Worker> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
_httpListener = new HttpListener();
}


protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{

_httpListener.Prefixes.Add($"http://*:5001/healthz/live/");    
_httpListener.Prefixes.Add($"http://*:5001/healthz/ready/");

_httpListener.Start();
_logger.LogInformation($"Healthcheck listening...");

while (!stoppingToken.IsCancellationRequested)
{
HttpListenerContext ctx = null;
try
{
ctx = await _httpListener.GetContextAsync();
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode == 995) return;
}

if (ctx == null) continue;

var response = ctx.Response;
response.ContentType = "text/plain";
response.Headers.Add(HttpResponseHeader.CacheControl, "no-store, no-cache");
response.StatusCode = (int)HttpStatusCode.OK;

var messageBytes = Encoding.UTF8.GetBytes("Healthy");
response.ContentLength64 = messageBytes.Length;
await response.OutputStream.WriteAsync(messageBytes, 0, messageBytes.Length);
response.OutputStream.Close();
response.Close();
}
}
}

我认为您还应该考虑保留Microsoft。NET。Sdk。工人

不要仅仅因为健康检查就更改整个sdk。

然后,您可以创建一个后台服务(就像主要工作程序一样(,以便更新文件以写入例如当前时间戳。背景健康检查工作人员的一个例子是:

public class HealthCheckWorker : BackgroundService
{
private readonly int _intervalSec;
private readonly string _healthCheckFileName;
public HealthCheckWorker(string healthCheckFileName, int intervalSec)
{
this._intervalSec = intervalSec;
this._healthCheckFileName = healthCheckFileName;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (true)
{
File.WriteAllText(this._healthCheckFileName, DateTime.UtcNow.ToString());
await Task.Delay(this._intervalSec * 1000, stoppingToken);
}
}
}

然后你可以添加这样的扩展方法:

public static class HealthCheckWorkerExtensions
{
public static void AddHealthCheck(this IServiceCollection services,
string healthCheckFileName, int intervalSec)
{
services.AddHostedService<HealthCheckWorker>(x => new HealthCheckWorker(healthCheckFileName, intervalSec));
}
}

有了这个,你可以添加健康检查支持的服务

.ConfigureServices(services =>
{
services.AddHealthCheck("hc.txt", 5);
})

我所做的就是添加Microsoft。NET。Sdk。Web到我的Worker,然后配置一个Web主机与Worker一起运行:

Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(builder =>
{
builder.UseStartup<Startup>();
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
services.AddLogging(builder =>
builder
.AddDebug()
.AddConsole()
);
});

完成后,剩下要做的就是像通常使用ASP一样映射健康检查端点。NET核心。

最新更新