在 ASP.NET Core 中使用 Consul 进行健康检查
在上一篇文章中,我写过如何使用Consul和 ASP.NET Core 实现客户端服务发现。如果您使用容器或微服务进行任何操作,这是一种非常有用的技术。
除了注册您的服务之外,如果服务注册中心可以跟踪服务的每个实例的运行状况,这将非常有帮助。如果客户端知道服务实例不再可用或不健康,它可以避免向该位置发送请求并处理由此产生的错误。在这篇文章中,我们将定义服务健康意味着什么,并了解如何使用 ASP.NET Core 和 Consul 实现健康检查。
服务运行状况
我们可以考虑通过几种方式检查服务实例的健康状况。在应用程序级别,如果服务正在运行、可以处理请求、不抛出异常等等,您可能会认为服务是健康的。要考虑的另一件事是运行服务的机器(或虚拟机或容器)的状态。您可能想知道内存消耗是多少、磁盘空间的使用百分比是多少,或者 CPU 利用率是多少?要考虑的第三类健康检查是外部依赖项的状态。例如,服务能否与数据库通信,能否与缓存服务交互,能否连接到给定的第 3 方供应商?即使服务本身已启动并正在运行,
领事健康检查
在我写这篇文章时,当前版本的 Consul (0.8.0) 支持 5 种不同类型的检查。
- HTTP 间隔检查- 将以给定的间隔向指定的 URL 发出 HTTP GET 请求。带有 2xx 状态代码的响应被认为是通过,而所有其他的都被认为是有问题的。这可以通过Web 应用程序中的端点
/status或端点轻松实现。/health - TCP 间隔检查- 尝试连接到给定的主机/IP 地址和端口号。如果可以建立连接,则认为健康检查状态为通过,否则状态为严重。这对于您自己的甚至是侦听端口的第 3 方应用程序很有用。
- 脚本间隔检查- 使用这种类型的检查,调用外部应用程序,执行编码操作,使用适当的系统代码退出,并可能生成一些输出。如果您的检查背后有更复杂的逻辑,那么这是一个不错的选择。您可以提供一个脚本(用 bash、Powershell、python 等编写),Consul 甚至会将输出捕获到它的 UI 中。
- Docker 间隔检查- 调用 Docker 容器内的外部应用程序。预计将对容器内运行的服务进行健康检查,并使用适当的退出代码退出。
- 生存时间(TTL)检查——检查的状态必须通过 Consul 的 HTTP 接口定期更新;通常由一些外部系统。因此,不是 Consul 启动健康检查,而是期望在给定的时间段内提供服务的状态。如果 TTL 过期,则状态将设置为关键。
向 ASP.NET Core 添加运行状况检查
可以选择在服务注册时包括健康检查。在某些情况下,这是上一篇文章中的注册码的样子。
public static IApplicationBuilder RegisterWithConsul(this IApplicationBuilder app,
IApplicationLifetime lifetime)
{
// Retrieve Consul client from DI
var consulClient = app.ApplicationServices
.GetRequiredService<IConsulClient>();
var consulConfig = app.ApplicationServices
.GetRequiredService<IOptions<ConsulConfig>>();
// Get server address information
var features = app.Properties["server.Features"] as FeatureCollection;
var addresses = features.Get<IServerAddressesFeature>();
var address = addresses.Addresses.First();
var uri = new Uri(address);
// Register service with consul
var registration = new AgentServiceRegistration()
{
ID = $"{consulConfig.Value.ServiceID}-{uri.Port}",
Name = consulConfig.Value.ServiceName,
Address = $"{uri.Scheme}://{uri.Host}",
Port = uri.Port,
Tags = new[] { "Students", "Courses", "School" }
};
consulClient.Agent.ServiceDeregister(registration.ID).Wait();
consulClient.Agent.ServiceRegister(registration).Wait();
lifetime.ApplicationStopping.Register(() => {
consulClient.Agent.ServiceDeregister(registration.ID).Wait();
});
该类AgentServiceRegistration有一个Checks属性,可用于提供与服务注册相关联的健康检查列表。让我们看一下向这个应用程序添加一些 Consul 健康检查。
HTTP 健康检查
var registration = new AgentServiceRegistration()
{
ID = $"{consulConfig.Value.ServiceID}-{uri.Port}",
Name = consulConfig.Value.ServiceName,
Address = $"{uri.Scheme}://{uri.Host}",
Port = uri.Port,
Tags = new[] { "Students", "Courses", "School" },
Checks = [new AgentCheckRegistration()
{
HTTP = $"{uri.Scheme}://{uri.Host}:{uri.Port}/api/health/status",
Notes = "Checks /health/status on localhost",
Timeout = TimeSpan.FromSeconds(3) ,
Interval = TimeSpan.FromSeconds(10)
}]
};
此检查期望/api/health/status应用程序中有一个可用的端点,供 Consul 向其发出 HTTP GET 请求。另请注意,您可以设置超时和检查间隔。
这是端点的样子。当然,您可以在 中添加更多代码HealthController以确定返回的条件Ok。
[Route("api/[controller]")]
public class HealthController : Controller
{
[HttpGet("status")]
public IActionResult Status() => Ok();
}
TCP 健康检查
var registration = new AgentServiceRegistration()
{
ID = $"{consulConfig.Value.ServiceID}-{uri.Port}",
Name = consulConfig.Value.ServiceName,
Address = $"{uri.Scheme}://{uri.Host}",
Port = uri.Port,
Tags = new[] { "Students", "Courses", "School" },
Checks = [new AgentCheckRegistration()
{
TCP = "localhost:8000",
Notes = "Runs a TCP check on port 8000",
Timeout = TimeSpan.FromSeconds(2),
Interval = TimeSpan.FromSeconds(5),
}]
};
有了这个 TCP 检查,Consul 会尝试打开到 localhost 上的端口 8000 的连接。请注意,这些类型的检查不仅限于本地连接。它们可用于检查是否可以连接到任何应用程序,侦听给定 IP 地址的任何端口。
脚本健康检查
var registration = new AgentServiceRegistration()
{
ID = $"{consulConfig.Value.ServiceID}-{uri.Port}",
Name = consulConfig.Value.ServiceName,
Address = $"{uri.Scheme}://{uri.Host}",
Port = uri.Port,
Tags = new[] { "Students", "Courses", "School" },
Checks = [new AgentCheckRegistration()
{
Script = "/path/to/script/check.py",
Notes = "Runs check.py in the project folder",
Timeout = TimeSpan.FromSeconds(2),
Interval = TimeSpan.FromSeconds(5),
}]
};
上面的代码设置了一个将调用 python 脚本的健康检查。如果脚本返回适当的退出代码,则检查成功。
这是我用来测试的简单脚本。
#! /usr/bin/env python3
import os, sys
print(os.getcwd())
sys.exit(os.EX_OK)
有了这些健康检查,您组织中的任何人都可以轻松地在 Consul UI 中查看您注册服务的状态。

对于健康检查状态的编程访问,我们可以直接利用 Consul 的HTTP API或使用 NuGet 包。
var _consulClient = new ConsulClient(c =>
{
var uri = new Uri(_configuration["consulConfig:address"]);
c.Address = uri;
});
var services = _consulClient.Agent.Services().Result.Response;
foreach (var service in services)
{
var checks = _consulClient.Health
.Checks(_configuration["consulConfig:serviceName"])
.Result;
foreach (var checkResult in checks.Response)
{
Console.WriteLine($"{checkResult.ServiceID} - {checkResult.Status.Status}");
}
}
结论
在这篇文章中,我们介绍了如何使用 Consul 和 PlayFab Consul NuGet 包注册运行状况检查。
Consul 只是在应用程序中设置健康检查的众多选项之一。在我写这篇文章时,看起来 ASP.NET 团队正在开发他们自己的健康检查支持版本。
https://cecilphillip.com/using-consul-for-health-checks-with-asp-net-core/
浙公网安备 33010602011771号