1
build / build-push (push) Successful in 27s

This commit is contained in:
wanghu
2026-09-03 08:39:36 +08:00
parent 2728235dc7
commit 8db5870084
2 changed files with 88 additions and 0 deletions
@@ -0,0 +1,85 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using StackExchange.Redis;
using YhCore.Repository;
namespace YhCore.WebApi.HealthChecks
{
/// <summary>
/// 数据库连通性检查:复用已注册的 YHDbContext(随 DatabaseProvider 自动适配 SqlServer/MySql)。
/// 每个检查自带 2 秒超时,防止连接池耗尽时探针自身挂死、反而探不出来。
/// </summary>
public class DbContextHealthCheck : IHealthCheck
{
private readonly YHDbContext _dbContext;
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(2);
public DbContextHealthCheck(YHDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
var probe = Task.Run(async () =>
{
await _dbContext.Database.OpenConnectionAsync(cancellationToken);
using var command = _dbContext.Database.GetDbConnection().CreateCommand();
command.CommandText = "SELECT 1";
await command.ExecuteScalarAsync(cancellationToken);
}, CancellationToken.None);
var finished = await Task.WhenAny(probe, Task.Delay(Timeout, CancellationToken.None));
if (finished != probe)
return HealthCheckResult.Unhealthy("database probe timed out after 2s");
await probe; // 传播异常
return HealthCheckResult.Healthy();
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("database probe failed: " + ex.Message, ex);
}
}
}
/// <summary>
/// Redis 连通性检查:复用全局单例 IConnectionMultiplexer(YhCore.Common.Cache 注册)。
/// </summary>
public class RedisHealthCheck : IHealthCheck
{
private readonly IConnectionMultiplexer _multiplexer;
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(2);
public RedisHealthCheck(IConnectionMultiplexer multiplexer)
{
_multiplexer = multiplexer;
}
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
if (!_multiplexer.IsConnected)
return HealthCheckResult.Unhealthy("redis connection is not established");
var probe = _multiplexer.GetDatabase().PingAsync();
var finished = await Task.WhenAny(probe, Task.Delay(Timeout, CancellationToken.None));
if (finished != probe)
return HealthCheckResult.Unhealthy("redis ping timed out after 2s");
var latency = await probe;
return HealthCheckResult.Healthy("ping " + latency);
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("redis probe failed: " + ex.Message, ex);
}
}
}
}
+3
View File
@@ -205,6 +205,9 @@ namespace YhCore.WebApi
{
endpoints.MapControllers();
// 免认证健康探针:健康 200 / 不健康 503(容器与负载均衡用)
endpoints.MapHealthChecks("/health");
// 根路径登录状态页:SSO 开启时未登录会先被中间件 302 到 CAS;登录后在此显示当前用户。
endpoints.MapGet("/", async context =>
{