Welcome to YARP

2023-11-15 06:00:12

目錄

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分散式跟蹤功能。