Welcome to YARP - 7.目标健康检查

目录

Welcome to YARP - 1.认识YARP并搭建反向代理服务

Welcome to YARP - 2.配置功能

Welcome to YARP - 3.负载均衡

Welcome to YARP - 4.限流

Welcome to YARP - 5.身份验证和授权

Welcome to YARP - 6.压缩、缓存

Welcome to YARP - 7.目标健康检查

Welcome to YARP - 8.分布式跟踪

介绍

在我们日常系统维护中,系统节点由于各种原因,如过载、资源泄漏、硬件故障等,偶尔会经历短暂的问题或完全失效。理想情况下,我们希望能够以主动的方式完全防止这些不幸的事件发生,但设计和构建这样一个理想系统通常成本过高。然而,还有一种更为经济的、反应性的方法, 旨在最大限度地减少故障对客户端请求造成的负面影响。

  • 主动目标健康检查(Active Destination Health Checks): 代理系统通过定期主动查询目标节点的状态来判断其健康状况。这样,代理能够主动了解节点的当前状态,并在需要时采取措施,停止将流量发送到不健康的节点。
  • 被动目标健康检查(Passive Destination Health Checks): 代理系统通过观察实际发送到目标节点的请求的响应来判断其健康状况。如果代理检测到目标节点返回了错误或不正常的响应,它可以将该节点标记为不健康,从而停止将流量发送到该节点,直到它恢复正常。

这种方式可以帮助系统在出现节点问题时更灵活地应对,以提供更可靠的服务。

主动健康检查

YARP 可以通过向指定的运行状况终结点发送定期探测请求并分析响应来主动监视目标运行状况。该分析由为集群指定的主动运行状况检查策略执行,并计算新的目标运行状况状态。最后,策略会根据 HTTP 响应代码(2xx 被视为正常)将每个目标标记为正常或不正常,并重新生成群集的正常目标集合。

YARP 提供了一系列配置选项,可以通过配置文件或代码,去控制集群中节点的主动健康检查,同时也提供了一种为每个目标定义专用健康终结点的方式,以满足不同需求的定制化。

配置文件示例

"Clusters": {
      "cluster1": {
        "HealthCheck": {
          "Active": {
            "Enabled": "true",
            "Interval": "00:00:10",
            "Timeout": "00:00:10",
            "Policy": "ConsecutiveFailures",
            "Path": "/api/health"
          }
        },
        "Metadata": {
          "ConsecutiveFailuresHealthPolicy.Threshold": "3"
        },
        "Destinations": {
          "cluster1/destination1": {
            "Address": "https://localhost:10000/"
          },
          "cluster1/destination2": {
            "Address": "http://localhost:10010/",
            "Health": "http://localhost:10020/"
          }
        }
      }

代码示例

var clusters = new[]
{
    new ClusterConfig()
    {
        ClusterId = "cluster1",
        HealthCheck = new HealthCheckConfig
        {
            Active = new ActiveHealthCheckConfig
            {
                Enabled = true,
                Interval = TimeSpan.FromSeconds(10),
                Timeout = TimeSpan.FromSeconds(10),
                Policy = HealthCheckConstants.ActivePolicy.ConsecutiveFailures,
                Path = "/api/health"
            }
        },
        Metadata = new Dictionary<string, string> { { ConsecutiveFailuresHealthPolicyOptions.ThresholdMetadataName, "5" } },
        Destinations =
        {
            { "destination1", new DestinationConfig() { Address = "https://localhost:10000" } },
            { "destination2", new DestinationConfig() { Address = "https://localhost:10010", Health = "https://localhost:10010" } }
        }
    }
};

配置

所有主动健康检查设置中,除了一个例外,其余的都在集群级别的 Cluster/HealthCheck/Active 部分指定。唯一的例外是一个可选的 Destination/Health 元素,用于指定单独的主动健康检查端点。实际的健康探测 URI 的构建方式是 Destination/Address(或设置 Destination/Health) + Cluster/HealthCheck/Active/Path

还可以通过 Yarp.ReverseProxy.Configuration 命名空间中的相应类型在代码中定义主动运行状况检查设置, 这与配置文件中的约定是一致的。

Cluster/HealthCheck/Active 部分和 ActiveHealthCheckConfig

  • Enabled - 指示是否为集群启用主动运行状况检查的标志。默认值 false
  • Interval - 发送运行状况探测请求的时间段。默认值 00:00:15
  • Timeout - 探测请求超时。默认值 00:00:10
  • Policy - 评估目标的活动运行状况状态的策略的名称。强制参数
  • Path - 所有集群目标上的运行状况检查路径。默认 null

Destination 部分和目标配置。

  • Health - 专用的运行状况探测终结点,例如 http://destination:12345/ 默认值 null ,并回退到 Destination/Address (系统将使用目标节点的基础地址作为健康检查的默认地址)。

内置策略

目前有一个内置的主动健康检查策略 - ConsecutiveFailuresHealthPolicy。该策略会计算连续的健康探测失败次数,并在达到给定的阈值后将目标标记为不健康。在第一次成功的响应之后,目标将被标记为健康,并将计数器重置。策略参数在集群的元数据中设置,如下所示:

  • ConsecutiveFailuresHealthPolicy.Threshold - 连续失败的主动健康探测请求的数量,需要达到才能将目标标记为不健康。默认值为 2。

设计 (被动健康检查)

YARP 中的被动健康检查的主要组件和工作流程如下:

  • 主组件:PassiveHealthCheckMiddleware,它位于请求处理管道中,负责分析目标返回的响应。
  • 工作流程:
    1. 对于每个属于启用了被动健康检查的集群的目标返回的响应,PassiveHealthCheckMiddleware 会调用为该集群指定的 IPassiveHealthCheckPolicy
    2. 策略分析给定的响应,评估新目标的被动健康状态,并调用 IDestinationHealthUpdater 来实际更新 DestinationHealthState.Passive 的值。
    3. 更新是在后台异步进行的,不会阻塞请求处理管道。
  • 不健康目标的处理:
    • 当一个目标被标记为不健康时,它将停止接收新的请求,直到在配置的一段时间后重新激活。
    • 激活意味着将目标的 DestinationHealthState.Passive 状态从不健康重置为未知,并重新构建集群的健康目标列表以包括它。
    • 重新激活是由 IDestinationHealthUpdater 在将目标的 DestinationHealthState.Passive 设置为不健康后立即安排重新激活的。
			(对代理请求的响应)
                  |
      PassiveHealthCheckMiddleware (被动健康检查中间件)
                  |
                  V
      IPassiveHealthCheckPolicy (被动健康检查策略)
                  |
    	  (评估新的被动健康状态)
                  |
    IDestinationHealthUpdater (目标健康状态更新器) --(异步更新被动状态)--> DestinationState.Health.Passive
                  |
                  V
      (安排重新激活) --(设置状态为未知)--> DestinationState.Health.Passive

扩展

被动运行状况检查子系统中有一个主要的扩展点,即 IPassiveHealthCheckPolicy

IPassiveHealthCheckPolicy

IPassiveHealthCheckPolicy 分析目标如何响应代理客户端请求,评估其新的被动运行状况状态,最后调用 IDestinationHealthUpdater.SetPassiveAsync 以创建异步任务,实际更新被动运行状况状态并重新生成正常目标集合。

以下是一个简单示例,演示了自定义的 IPassiveHealthCheckPolicy,在代理请求的第一次不成功的响应时将目标标记为不健康。

public class FirstUnsuccessfulResponseHealthPolicy : IPassiveHealthCheckPolicy
{
    private static readonly TimeSpan _defaultReactivationPeriod = TimeSpan.FromSeconds(60);
    private readonly IDestinationHealthUpdater _healthUpdater;

    public FirstUnsuccessfulResponseHealthPolicy(IDestinationHealthUpdater healthUpdater)
    {
        _healthUpdater = healthUpdater;
    }

    public string Name => "FirstUnsuccessfulResponse";

    public void RequestProxied(HttpContext context, ClusterState cluster, DestinationState destination)
    {
        var error = context.Features.Get<IForwarderErrorFeature>();
        if (error is not null)
        {
            var reactivationPeriod = cluster.Model.Config.HealthCheck?.Passive?.ReactivationPeriod ?? _defaultReactivationPeriod;
            _healthUpdater.SetPassive(cluster, destination, DestinationHealth.Unhealthy, reactivationPeriod);
        }
    }
}

可用的目标集合

目标健康状态用于确定哪些目标适合接收代理请求。每个集群都在 ClusterDestinationState 类型的 AvailableDestinations 属性上维护自己的可用目标列表。当任何目标的健康状态发生变化时,该列表将被重新构建。IClusterDestinationsUpdater 控制这个过程,并调用在集群上配置的 IAvailableDestinationsPolicy 来实际选择从所有集群目标中可用的目标。提供了以下内置策略,如果需要,还可以实现自定义策略。

  • HealthyAndUnknown - 检查每个 DestinationState ,如果以下所有语句均为 TRUE,则将其添加到可用目标列表中。如果没有可用的目标,则请求将收到 503 错误。这是默认策略。
    • 主动健康检查在集群上是被禁用的,或者 DestinationHealthState.Active != DestinationHealth.Unhealthy( 这意味着如果目标节点被标记为主动不健康,那么主动健康检查会被禁用 )
    • 被动健康检查在集群上是被禁用的,或者 DestinationHealthState.Passive != DestinationHealth.Unhealthy。( 这意味着如果目标节点被标记为被动不健康,那么被动健康检查会被禁用 )
  • HealthyOrPanic - 首先调用 HealthyAndUnknown 策略以获取可用目标。如果此调用均未返回任何目标,则会将所有集群的目标标记为可用。

注意:无论给定集群上是否启用任何健康检查,都将始终调用配置在集群上的可用目标策略。已禁用健康检查的健康状态设置为未知。

配置

配置文件示例

"Clusters": {
      "cluster1": {
        "AvailableDestinationsPolicy": "HealthyOrPanic",
        "HealthCheck": {
          "Passive": {
            "Enabled": "true"
          }
        },
        "Destinations": {
          "cluster1/destination1": {
            "Address": "https://localhost:10000/"
          },
          "cluster1/destination2": {
            "Address": "http://localhost:10010/"
          }
        }
      }

代码示例

var clusters = new[]
{
    new ClusterConfig()
    {
        ClusterId = "cluster1",
        HealthCheck = new HealthCheckConfig
        {
            AvailableDestinationsPolicy = HealthCheckConstants.AvailableDestinations.HealthyOrPanic,
            Passive = new PassiveHealthCheckConfig
            {
                Enabled = true
            }
        },
        Destinations =
        {
            { "destination1", new DestinationConfig() { Address = "https://localhost:10000" } },
            { "destination2", new DestinationConfig() { Address = "https://localhost:10010" } }
        }
    }
};

总结

本章我们介绍了 YARP 的 目标健康检查功能。它有助于提高系统的可用性、稳定性,并帮助及时发现和应对服务故障。 本章暂时没有准备代码示例,有空了再补上吧。

下篇文章我们继续介绍 YARP分布式跟踪功能。

posted @ 2023-11-15 00:56  coding-y  阅读(1179)  评论(3编辑  收藏  举报