前言 1.健康检查系统来源背景 互联网产品对用户体验提出了很高的要求,但常常由于技术侧原因,发生服务响应慢或者服务不可用等一系列影响用户体验的问题,导致业务中断,影响收
前言
1.健康检查系统来源背景
互联网产品对用户体验提出了很高的要求,但常常由于技术侧原因,发生服务响应慢或者服务不可用等一系列影响用户体验的问题,导致业务中断,影响收入。影响服务不可用和响应慢的因素很多,可能是服务硬件损坏、光纤被挖断,可能是请求量过大导致数据库CPU负载、磁盘IO过高等等。
2.健康检查系统的作用
要保证系统高可用,主要就是消除单节点故障,消除单节点故障是系统高可用的常用手段。消除单节点有一个很重要的前提是发现问题节点,把问题节点踢除或者把流量切换到其他正常节点。
如何“发现问题节点”,就是系统健康检查需要做的事情。
3.如何涉及健康检查系统
谈论如何做健康检查前,首先要弄明白的是要检查的对象究竟是谁。对象可以网络连接,可以是一个小小的功能组件,可以是一个进程,可以是服务集群,也可以是机房单元。在开发AspNet Core应用的时候,我们经常会为该应用公布一个特殊的检测接口出来。该接口的目的很简单,告诉外界程序当前程序现在是可以访问或者不能访问的,便于外界做出相应的操作,比如监控报警,页面通知用户稍作等待等。
一、分布式服务的健康检查系统
1.官方包的使用
1、添加健康检查类和响应输出方法
/// <summary>
/// mysql健康检查
/// </summary>
public class MySQLHealthCheck : IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
return await Task.FromResult(HealthCheckResult.Healthy()).ConfigureAwait(false);
}
catch
{
return await Task.FromResult(HealthCheckResult.Unhealthy("From Sql Serve")).ConfigureAwait(false);
}
}
}
/// <summary>
/// redis健康检查
/// </summary>
public class RedisHealthCheck : IHealthCheck
{
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
return Task.FromResult(HealthCheckResult.Healthy());
}
}
public static class Response
{
/// <summary>
/// 返回指定格式
/// </summary>
/// <param name="context"></param>
/// <param name="result"></param>
/// <returns></returns>
private static Task WriteResponse(HttpContext context, HealthReport result)
{
context.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 context.Response.WriteAsync(json.ToString());
}
}
2、注入服务
//添加健康检查服务
builder.Services.AddHealthChecks()
.AddCheck<MySQLHealthCheck>("mysql_check")
.AddCheck<RedisHealthCheck>("redis_check");
//健康检查服务接口地址
app.MapHealthChecks("/mysqlhealth", new HealthCheckOptions()
{//mysql
Predicate = s => s.Name.Equals("mysql_check"),
ResponseWriter = (HttpContext context, HealthReport result) =>
{
context.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 context.Response.WriteAsync(json.ToString());
}
});
app.MapHealthChecks("/redishealth", new HealthCheckOptions() //redis
{
Predicate = s => s.Name.Equals("redis_check"),
ResponseWriter = (HttpContext context, HealthReport result) =>
{
context.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 context.Response.WriteAsync(json.ToString());
}
});
通过访问地址:http://ip:端口/mysqlhealth 查看mysql连接状态
通过访问地址:http://ip:端口/redishealth 查看redis连接状态
2.第三方包的使用
2.1 第三方包
GitHub:https://github.com/xabaril/AspNetCore.Diagnostics.HealthChecks
支持的服务健康检查的包有
Install-Package AspNetCore.HealthChecks.ApplicationStatus
Install-Package AspNetCore.HealthChecks.ArangoDb
Install-Package AspNetCore.HealthChecks.Aws.S3
Install-Package AspNetCore.HealthChecks.Aws.SecretsManager
Install-Package AspNetCore.HealthChecks.Aws.Sns
Install-Package AspNetCore.HealthChecks.Aws.Sqs
Install-Package AspNetCore.HealthChecks.Aws.SystemsManager
Install-Package AspNetCore.HealthChecks.Azure.IoTHub
Install-Package AspNetCore.HealthChecks.AzureDigitalTwin
Install-Package AspNetCore.HealthChecks.AzureKeyVault
Install-Package AspNetCore.HealthChecks.AzureServiceBus
Install-Package AspNetCore.HealthChecks.AzureStorage
Install-Package AspNetCore.HealthChecks.Consul
Install-Package AspNetCore.HealthChecks.CosmosDb
Install-Package AspNetCore.HealthChecks.DocumentDb
Install-Package AspNetCore.HealthChecks.DynamoDB
Install-Package AspNetCore.HealthChecks.Elasticsearch
Install-Package AspNetCore.HealthChecks.EventStore
Install-Package AspNetCore.HealthChecks.EventStore.gRPC
Install-Package AspNetCore.HealthChecks.Gcp.CloudFirestore
Install-Package AspNetCore.HealthChecks.Gremlin
Install-Package AspNetCore.HealthChecks.Hangfire
Install-Package AspNetCore.HealthChecks.IbmMQ
Install-Package AspNetCore.HealthChecks.Kafka
Install-Package AspNetCore.HealthChecks.Kubernetes
Install-Package AspNetCore.HealthChecks.MongoDb
Install-Package AspNetCore.HealthChecks.MySql
Install-Package AspNetCore.HealthChecks.Nats
Install-Package AspNetCore.HealthChecks.Network
Install-Package AspNetCore.HealthChecks.Npgsql
Install-Package AspNetCore.HealthChecks.OpenIdConnectServer
Install-Package AspNetCore.HealthChecks.Oracle
Install-Package AspNetCore.HealthChecks.RabbitMQ
Install-Package AspNetCore.HealthChecks.RavenDB
Install-Package AspNetCore.HealthChecks.Redis
Install-Package AspNetCore.HealthChecks.SendGrid
Install-Package AspNetCore.HealthChecks.SignalR
Install-Package AspNetCore.HealthChecks.Solr
Install-Package AspNetCore.HealthChecks.SqLite
Install-Package AspNetCore.HealthChecks.SqlServer
Install-Package AspNetCore.HealthChecks.System
Install-Package AspNetCore.HealthChecks.Uris
2.2 安装包
AspNetCore.HealthChecks.UI
AspNetCore.HealthChecks.UI.Client
AspNetCore.HealthChecks.UI.InMemory.Storage
AspNetCore.HealthChecks.MySql
AspNetCore.HealthChecks.Redis
2.3 设置启动
1、自写类监控检查
//添加健康检查服务
builder.Services.AddHealthChecks()
.AddCheck<MySqlHealthCheck>("mysql_check")
.AddCheck<RedisHealthCheck>("redis_check");
builder.Services.AddHealthChecksUI().AddInMemoryStorage();
//健康检查服务接口地址
app.MapHealthChecks("/mysqlhealth", new HealthCheckOptions()
{
Predicate = s => s.Name.Equals("mysql_check"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapHealthChecks("/redishealth", new HealthCheckOptions()
{
Predicate = s => s.Name.Equals("redis_check"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapHealthChecksUI();
启动程序访问:/healthchecks-ui 地址 2、相关包监控检查
//添加健康检查服务
builder.Services.AddHealthChecks()
.AddTypeActivatedCheck<MySqlHealthCheck>("mysql_check", args: new[] { "server=120.79.63.89;userid=root;pwd=123456;port=3308;database=DB_SY_ERP;sslmode=none" })
.AddTypeActivatedCheck<RedisHealthCheck>("redis_check", args: new[] { "localhost:6379,defaultDatabase=1" });
builder.Services.AddHealthChecksUI(setup =>
{
//可配置
setup.SetEvaluationTimeInSeconds(5); // UI 配置轮询间隔(以秒为单位)
setup.SetApiMaxActiveRequests(1); // 运行状况检查 UI 后端 API 的最大活动请求数
setup.MaximumHistoryEntriesPerEndpoint(50);//提供的最大历史记录条目数
//setup.AddHealthCheckEndpoint("endpoint1", "http://localhost:8001/healthz");
//setup.AddHealthCheckEndpoint("endpoint2", "http://remoteendpoint:9000/healthz");
//setup.AddWebhookNotification("webhook1", uri: "http://httpbin.org/status/200?code=ax3rt56s", payload: "{...}");
}).AddInMemoryStorage();
//健康检查服务接口地址
app.MapHealthChecks("/mysqlhealth", new HealthCheckOptions()
{
Predicate = s => s.Name.Equals("mysql_check"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapHealthChecks("/redishealth", new HealthCheckOptions()
{
Predicate = s => s.Name.Equals("redis_check"),
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapHealthChecksUI();
启动程序访问:/healthchecks-ui 地址 启动redis看下