网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using System.Net.Http;
using System.Net.Sockets;
using System.Threading;
using Dpz.Core.Public.ViewModel.RequestEvent;
using Dpz.Core.Public.ViewModel.Response;
using ProtocolType = Dpz.Core.EnumLibrary.ProtocolType;

namespace Dpz.Core.Service.Event;

public class HealthCheckHandler(
    IHealthCheckService healthCheckService,
    IHttpClientFactory httpClientFactory
) : IRequestHandler<HealthCheckRequest>
{
    private readonly HttpClient _httpClient = httpClientFactory.CreateClient("edge");
    private static Lazy<List<HealthCheckResponse>>? _lazyHealthChecks;

    public async Task Handle(HealthCheckRequest request, CancellationToken cancellationToken)
    {
        if (_lazyHealthChecks is not { IsValueCreated: true })
        {
            var healthChecks = await healthCheckService.GetHealthChecksAsync();
            _lazyHealthChecks = new Lazy<List<HealthCheckResponse>>(() => healthChecks);
        }

        foreach (var item in _lazyHealthChecks.Value)
        {
            var currentInterval = DateTime.Now - item.LastCheckTime;
            if (currentInterval >= item.Interval)
            {
                var result = await CheckAsync(item);
                item.LastCheckDuration = result.LastCheckDuration;
                item.LastCheckTime = result.LastCheckTime;
            }
        }
    }

    private async Task<HealthCheckResultResponse> CheckAsync(HealthCheckResponse healthCheck)
    {
        var checkTimer = Stopwatch.StartNew();
        var retries = 0;
        Exception? lastError = null;

        while (retries < healthCheck.RetryCount)
        {
            try
            {
                using var cts = new CancellationTokenSource(healthCheck.Timeout);
                var isHealthy = await CheckEndpointAsync(healthCheck, cts.Token);

                return new HealthCheckResultResponse()
                {
                    Status = isHealthy ? HealthStatus.Healthy : HealthStatus.Unhealthy,
                    LastCheckDuration = checkTimer.Elapsed,
                    LastCheckTime = DateTime.Now,
                    ErrorMessage = lastError?.Message,
                };
            }
            catch (Exception ex)
            {
                lastError = ex;
                retries++;
                // 重试间隔
                await Task.Delay(1000);
            }
        }

        return new HealthCheckResultResponse()
        {
            Status = HealthStatus.Unhealthy,
            LastCheckDuration = checkTimer.Elapsed,
            LastCheckTime = DateTime.Now,
            ErrorMessage = lastError?.Message,
        };
    }

    private async Task<bool> CheckEndpointAsync(
        HealthCheckResponse healthCheck,
        CancellationToken cancellationToken
    )
    {
        return healthCheck.Protocol switch
        {
            ProtocolType.Http or ProtocolType.Https => await CheckHttpAsync(
                healthCheck,
                cancellationToken
            ),
            ProtocolType.Tcp => CheckTcp(healthCheck),
            _ => throw new NotSupportedException($"协议 {healthCheck.Protocol} 不支持"),
        };
    }

    private async Task<bool> CheckHttpAsync(
        HealthCheckResponse healthCheck,
        CancellationToken cancellationToken
    )
    {
        var response = await _httpClient.GetAsync(healthCheck.Endpoint, cancellationToken);
        return response.IsSuccessStatusCode;
    }

    private bool CheckTcp(HealthCheckResponse healthCheck)
    {
        var parts = healthCheck.Endpoint.Split(':');
        using var tcpClient = new TcpClient();
        return tcpClient.ConnectAsync(parts[0], int.Parse(parts[1])).Wait(healthCheck.Timeout);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码实现了一个健康检查处理程序 HealthCheckHandler,用于定期检查一组服务的健康状态。它使用了依赖注入的方式来获取健康检查服务和 HTTP 客户端工厂。以下是代码的主要功能和结构的详细解释:

主要功能

  1. 健康检查请求处理

    • HealthCheckHandler 类实现了 IRequestHandler<HealthCheckRequest> 接口,负责处理健康检查请求。
    • Handle 方法中,它会检查每个健康检查项的上次检查时间与当前时间的间隔,如果超过了设定的检查间隔,则会执行健康检查。
  2. 懒加载健康检查列表

    • _lazyHealthChecks 是一个 Lazy<List<HealthCheckResponse>> 类型的字段,用于懒加载健康检查列表。只有在第一次访问时才会从 healthCheckService 中获取健康检查项。
  3. 健康检查逻辑

    • 对于每个健康检查项,CheckAsync 方法会被调用。该方法会尝试多次检查服务的健康状态,直到达到最大重试次数。
    • 如果检查成功,返回健康状态为 Healthy,否则返回 Unhealthy,并记录最后的检查持续时间和错误信息。
  4. 支持多种协议

    • CheckEndpointAsync 方法根据健康检查项的协议类型(HTTP/HTTPS 或 TCP)调用相应的检查方法。
    • 对于 HTTP/HTTPS,使用 CheckHttpAsync 方法发送 GET 请求并检查响应状态。
    • 对于 TCP,使用 CheckTcp 方法尝试连接到指定的主机和端口。
  5. 异常处理与重试机制

    • CheckAsync 方法中,使用了重试机制来处理可能的异常。如果在重试次数内仍然失败,则返回 Unhealthy 状态。

代码结构

  • 构造函数

    • 接受 IHealthCheckServiceIHttpClientFactory 的实例,用于获取健康检查数据和创建 HTTP 客户端。
  • Handle 方法

    • 处理健康检查请求,检查每个健康检查项的状态并执行必要的检查。
  • CheckAsync 方法

    • 执行具体的健康检查逻辑,处理重试和异常。
  • CheckEndpointAsync 方法

    • 根据协议类型调用相应的检查方法。
  • CheckHttpAsync 和 CheckTcp 方法

    • 分别实现 HTTP 和 TCP 的健康检查逻辑。

总结

整体上,这段代码实现了一个灵活的健康检查机制,能够定期检查多个服务的健康状态,并支持 HTTP 和 TCP 协议。它通过懒加载和重试机制提高了性能和可靠性,适合用于微服务架构中的服务监控。

loading