Sentinel Go 1.0リリース:W11(独身の日)向け高可用性フロー制御ミドルウェア


このブログでは、Sentinelが2020年のW11(独身の日)に向けてクラウドネイティブサービスの安定性をどのように確保したかを説明し、高可用性保護の複数のコアシナリオを探っています。

著者:オープンソースプロジェクト「Sentinel」ディレクター、Zhao Yihao(Suhe)氏

はじめに

近年、多くの開発者がマイクロサービスの安定性に大きな関心を寄せています。ビジネスがモノリシックから分散型アーキテクチャに進化し、新しいデプロイメントモードを採用するにつれて、サービス間の依存関係はますます複雑になっています。この複雑さの増大により、企業はシステムの高可用性を維持することが難しくなります。

例えば、本番環境では、次のような様々な不安定な状況に遭遇することがあります。

  • 大規模なプロモーション時に、瞬間的なピークトラフィックによってシステムの負荷上限を超えてしまい、システムがクラッシュしてユーザーが注文できなくなってしまうことがある。

  • 予期せぬホットスポットアイテムのトラフィックがキャッシュを突破し、データベースが敗退し、通常のトラフィックを占める。

  • 呼び出し側が不安定なサードパーティサービスに引きずられ、スレッドプールが満杯になり、呼び出しが蓄積され、結果的にコールリンク全体が動かなくなった。

このような不安定なシナリオは深刻な結果を招く可能性がありますが、トラフィックや依存性に関連する高可用性の保護を無視している可能性が高いです。このような不安定な要因の影響を防ぐにはどうすればよいでしょうか。トラフィックに対する高可用性保護を実現するにはどうすればよいでしょうか?どうすればサービスの「安定性」を確保できるのでしょうか?そんなときに頼りになるのが、AlibabaのW11(独身の日)で採用された高可用性保護ミドルウェア「Sentinel」です。今年のTmall W11 ショッピング・フェスティバル(独身の日)では、トラフィックのピーク時にSentinelが何万ものAlibabaのサービスの安定性を完璧に確保しましたが、先日、Sentinel Go 1.0 GAリリースが正式に発表されました。ここでは、Sentinel Goの中核となるシナリオと、コミュニティがクラウドネイティブ領域で探求してきたことを見てみましょう。

Sentinelの紹介

Sentinelは、Alibabaがオープンソースで提供している分散サービスアーキテクチャ用のスロットリングコンポーネントです。Sentinelはトラフィックを分岐点として、開発者がトラフィックのスロットリング、トラフィックシェーピング、サーキットブレーキング、適応型システム保護などのさまざまな方法でマイクロサービスの安定性を確保するのに役立ちます。Sentinelは、フラッシュセール、コールドスタート、ロードシフティング、クラスタフローコントロール、利用できないサービスのダウンストリームのリアルタイム停止など、過去10年間のAlibabaのW11(独身の日)ショッピング・フェスティバル におけるコアトラフィックシナリオをサポートしてきました。マイクロサービスの高可用性を確保するための強力なツールとなります。Java、Go、C ++などのプログラミング言語をサポートしています。また、Service Meshを高可用性で保護するために、Istio/Envoyのグローバルトラフィック・スロットリングをサポートしています。

今年初め、Sentinelコミュニティは、マイクロサービスとGo言語の基本コンポーネントの高可用性保護とフォールトトレランスのネイティブサポートを提供するSentinel Goの立ち上げを発表しました。これはSentinelにとって、多様化とクラウドネイティブモードに向けた新たな一歩となります。この半年間で、コミュニティは10近いバージョンをリリースし、コアとなる高可用性保護と耐障害性の機能を徐々に揃えてきました。また、同コミュニティは、dubbo-goや、Ant Financial Modular Open Smart Network(MOSN)コミュニティなどの他のオープンソースコミュニティと連携することで、オープンソースのエコシステムを継続的に拡大しています。

最近、Sentinel Go 1.0 GAバージョンが正式にリリースされ、生産フェーズが正式に開始されました。Sentinel Go 1.0は、トラフィックのスロットリング、トラフィックシェーピング、同時実行制御、サーキットブレーキング、システムアダプティブプロテクション、ホットスポットプロテクションなど、Javaの高可用性保護機能と耐障害性機能に沿ったものとなっています。さらに、このバージョンでは、主流のオープンソースエコシステムをカバーし、Gin、gRPC、go-micro、dubbo-goなどの一般的なマイクロサービスフレームワークのアダプタを提供し、etcd、Nacos、Consulなどの動的データソースの拡張サポートを提供します。Sentinel Goは、クラウドネイティブな方向に進化しています。V 1.0では、KubernetesのCustom Resource Definition(CRD)データソース、KubernetesのHorizontal Pod Autoscaler(HPA)など、いくつかのクラウドネイティブな側面が検討されました。Sentinel Goのバージョンでは、予想されるスロットリングのシナリオは、マイクロサービスアプリケーション自体に限定されません。Go言語のエコシステムでは、クラウドネイティブの基本コンポーネントが高い割合を占めています。しかし、これらのクラウドネイティブコンポーネントには、きめ細かく適応性のある保護や耐障害性の仕組みがないことが多くあります。このような場合、いくつかのコンポーネント拡張メカニズムを組み合わせ、Sentinel Goを使って自社のビジネスの安定性を守ることができます。

Sentinelのボトムレイヤーでは、高性能なスライディングウィンドウを使用して数秒以内にメトリクスをカウントし、トークンバケット、リーキーバケット、適応型フローコントロールアルゴリズムを組み合わせて、コアとなる高可用性保護機能を実証しています。

では、Sentinel Goを使ってマイクロサービスの安定性を確保するにはどうすればよいのでしょうか。いくつかの典型的なアプリケーションシナリオを見てみましょう。

高可用性保護のコアシナリオ

1. トラフィックのスロットルと割り当て

トラフィックはランダムで予測できません。トラフィックのピークは、ある瞬間から別の瞬間に発生する可能性があります。毎年W11(独身の日)の00:00には、これに対処しなければなりません。しかし、私たちのシステムの容量は常に制限されています。突発的なトラフィックがシステムの容量を超えると、リクエストが処理されなかったり、蓄積されたリクエストの処理が遅くなったりします。そして、CPU/負荷が高くなり、システムがクラッシュしてしまうのです。そのため、このようなトラフィックの急増を制限し、できるだけ多くのリクエストを処理しながらサービスがクラッシュしないようにする必要があります。トラフィック・スロットリングは、パルス・トラフィックなどのシナリオに適用できます。

ウェブポータルやサービスプロバイダのシナリオでは、トラフィックのピークによってサービスプロバイダが圧倒されないように保護する必要があります。このとき、トラフィック・スロットリングは、サービス・プロバイダのサービス能力に基づいて、あるいは特定のサービス・コンシューマに基づいて実行されることが多くあります。プレストレステストに基づいてコアインタフェースの余裕度を評価し、QPS(Queries per Second)モードのトラフィックスロットリングルールを設定します。1秒あたりのリクエスト数が設定した閾値を超えると、過剰なリクエストは自動的に拒否されます。

以下は、Sentinel のトラフィック・スロットリング・ルールの最も単純な構成例です。

_, err = flow.LoadRules([]*flow.Rule{
    {
        Resource:          "some-service", // Tracking point resource name
        Count:             10, // If the threshold is 10, it is the second-level dimension statistics by default, which indicates that the request cannot exceed 10 times per second.
        ControlBehavior:   flow.Reject, // The control effect is direct rejection, the time interval between requests is not controlled, and the requests are not queued
    },
})

2、ウォームアップ・トラフィック・スロットリング

システムの使用リソース量が少ない状態が長く続き、トラフィックが急増した場合、システムの使用リソース量がそのまま高レベルになると、すぐにシステムがクラッシュしてしまうことがあります。例えば、新しく起動したサービスでは、データベース接続プールが初期化されておらず、キャッシュも空になっている場合があります。トラフィックの急増により、サービスは簡単にクラッシュしてしまいます。トラフィックのスムージングやシフト制限をせずに、従来のトラフィック・スロットリング・モードを採用すると、システムが停止する危険性もあります。(例えば、一瞬にして同時性が非常に高くなった場合など) このシナリオに対しては、Sentinel のトラフィック・スロッティング・モードを使用してトラフィックを制御し、一瞬にしてすべてのトラフィックを許可するのではなく、一定期間内に上限のしきい値までゆっくりと増加させることができます。同時に、リクエスト間隔制御やキューイングなどの制御効果と組み合わせることで、大量のリクエストが同時に処理されることを防ぎます。これにより、冷え切ったシステムが温まり、負担がかかるのを防ぐことができます。

3、コンカレンシーコントロールとサーキットブレーキング

サービスはしばしば他のモジュールを呼び出すことがあります。それは他のリモートサービス、データベース、またはサードパーティのAPIであるかもしれません。例えば、お客様が支払いを行う際には、UnionPayが提供するAPIを呼び出す必要があります。また、商品の価格を問い合わせる際には、データベースへの問い合わせが必要になることもあります。しかし、依存サービスの安定性は保証されていません。依存サービスが不安定になると、リクエストの応答時間が長くなり、サービスを呼び出すメソッドの応答時間も長くなり、スレッドが溜まっていきます。最終的には、ビジネスのスレッドプールを使い果たしてしまい、サービスが利用できなくなる可能性があります。

最近のマイクロサービス・アーキテクチャは分散型で、多くのサービスで構成されています。異なるサービスがお互いに呼び出し、複雑なコールチェーンを形成しています。コールチェーンでは、前述の問題が拡大する可能性があります。複雑なチェーンの中の1つのリンクが不安定になると、カスケードが発生し、最終的にチェーン全体が利用できなくなる可能性があります。Sentinel Goでは、遅いコールなどの不安定な要因によるアンアベイラビリティを防ぐために、以下の機能を提供しています。

  • コンカレンシーコントロール(アイソレーションモジュール)。軽量の隔離方法として、一部のコールの同時実行数(つまり進行中のコールの数)を制御して、遅いコールが多すぎて正常なコールが混雑するのを防ぎます。

  • サーキットブレーキング(Circuit Breaker module)。不安定な弱い依存性のある呼び出しの回路を自動的に切断します。不安定なコールを一時的に遮断し、局所的な不安定性による全体的なクラッシュを回避します。

Sentinel Goのフォールトトレランス機能は、このサーキットブレーカーモードに基づいており、サービスに不安定要因(応答時間が長い、エラー率が高いなど)が発生した場合、サービスコールを一時的に遮断し、しばらく待ってから再試行します。これにより、不安定なサービスへの影響を防ぐだけでなく、サービスの呼び出し側をクラッシュから保護することができます。Sentinelは2つのブレークポリシーをサポートしています。応答時間(スローコール率)に基づくものと、エラー(エラー率/エラー数)に基づくもので、様々な不安定なシナリオから効果的に保護することができます。

なお、サーキットブレーカーモードは、一般的に弱い依存性のコールに適用されます。つまり、サーキットブレーカーは、メインのサービスプロセスに影響を与えないため、開発者は、サーキットブレーカー後のフォールバックロジックと戻り値を設計する必要があります。また、サービス呼び出し側がサーキットブレーキングメカニズムを使用している場合でも、追加の保護のためにHTTPまたはRPC(Remote Procedure Call)クライアント上でリクエストタイムアウト時間を設定する必要があります。

4、 ホットスポットの保護

トラフィックはランダムで予測できません。大量のトラフィックによるシステムクラッシュを防ぐために、通常はコアAPIに対してトラフィックのスロットリングルールを設定します。しかし、一般的なトラフィックスロットリングルールでは不十分なシナリオもあります。たとえば,多くの人気アイテムは,大規模なプロモーションが行われているピーク時に,非常に高い一時的なページビュー(PV)を記録します。一般的には、人気のあるアイテムを予測し、これらのリクエストに関する情報をキャッシュすることができます。PV数が多い場合は、データベースにアクセスしなくても、事前に読み込んだキャッシュから商品情報を素早く返すことができます。しかし、プロモーションでは、事前に情報がキャッシュされていない予想外の人気商品が出てくることがあります。このような予想外の人気商品に対するPV数が急激に増加すると、大量のリクエストがデータベースに転送されることになります。その結果、データベースへのアクセス速度が低下し、人気アイテムリクエスト用のリソースプールが占有され、システムがクラッシュする可能性があります。このシナリオでは、Sentinelのホットスポット・パラメータ・トラフィック・スロットリング(中国語ページ)機能を使って、ホットスポット・パラメータを自動的に識別し、各ホットスポット値のQPSまたはコンカレンシーを制御することができます。これにより、ホットスポット・パラメータを持つアクセス・リクエストが通常のスケジューリング・リソースを占有することを効果的に防ぐことができます。

別の例を見てみましょう。各ユーザーがAPIを呼び出す頻度を制限したい場合、API名とuserIdをトラッキングポイントのリソース名として使用するのは得策ではありません。このシナリオでは、WithArgs(xxx)を使用してAPIトラッキングポイントにパラメータとしてuserIdを送信し、ホットスポットルールを構成して各ユーザの呼び出し頻度を制限することができます。Sentinelは、より正確なトラフィックの絞り込みのために、特定の値の独立したトラフィックの絞り込みもサポートしています。他のルールと同様に、ホットスポットのトラフィック・スロッティング・ルールも、動的なデータ・ソースに基づいて動的に構成することができます。

Sentinel Goが提供するDubboやgRPCなどのRPCフレームワーク統合モジュールは、トラッキングポイントでRPCコールするパラメータのリストを自動的に運びます。対応するパラメータの位置に対して、ホットスポットのトラフィックのスロットリングルールを設定することができます。なお、特定の値のトラフィック・スロットルを設定する必要がある場合、タイプシステムの制限により、現在サポートされているのは基本タイプと文字列タイプのみです。

Sentinel Go のホットスポットのトラフィック スロットリングは、キャッシュ終端メカニズムとトークンバケットメカニズムに基づいて実装されています。Sentinelは、ホットスポットパラメータを識別するためにLRU (Least Recently Used)、LFU (Least Frequently Used)、またはARC (Adaptive Replacement Cache)ポリシーなどのキャッシュ交換メカニズムを使用し、各ホットスポットパラメータのPV量を制御するためにトークンバケットメカニズムを使用します。現在のSentinel Goのバージョンでは、ホットスポットパラメータの収集にLRU戦略を使用していますが、コミュニティの一部の貢献者は、消去メカニズムを最適化するためにProject Review (PR)を提出しました。次のバージョンでは、コミュニティはさまざまなシナリオの要件を満たすために、より多くのキャッシュ消去メカニズムを導入する予定です。

5、アダプティブシステム保護

以上のようなトラフィック保護のシナリオで、すべてが大丈夫なのでしょうか。実際にはそうではありません。多くの場合、インターフェイスの正確な容量を事前に正確に評価することはできません、コア・インターフェイスのトラフィック特性(パルスがあるかどうかなど)を予測することもできません。このとき、事前に設定したルールでは、現在のサービスノードを効果的に保護できないことがあります。場合によっては、突然、マシンの負荷やCPU使用率が急激に増加し始めることがあります。しかし、何が原因なのかをすぐに確認する方法がなく、この例外に対処するには遅すぎます。この時、必要なのは損失を早く止めることです。このような問題に対処するために、Sentinel Goは、システムメトリクスとサービス容量を組み合わせてトラフィックを動的に調整する適応型システム保護ルールを提供しています。

Sentinelの適応型システム保護ルールは、TCPのボトルネック帯域幅と往復伝搬時間(BBR)アルゴリズムの考え方を参考にしており、システム負荷、CPU使用率、サービスのポータルQPS、応答時間、同時実行性など、複数の次元の監視指標を組み合わせています。アダプティブ・システム・プロテクション戦略は、インバウンド・システム・トラフィックとシステム負荷のバランスをとり、システムの安定性を最大化するとともに、スループットを最大化します。システムルールは、サービスが故障しないように、サービス全体のバックアップ保護ポリシーとして使用できます。この方法は、CPU負荷の高いシナリオに有効です。同時に、コミュニティでは、自動制御理論や強化学習と組み合わせた適応型トラフィックスロットリングの効果や適用シナリオの改善も継続的に行っています。将来のバージョンでは、より多くの利用可能なシナリオに対応するために、より実験的な適応型トラフィック・スロットリング・ポリシーも導入する予定です。

クラウドネイティブの探求

クラウドネイティブであることは、Sentinel Goの進化において最も重要な側面です。Sentinel Go 1.0 GAバージョンの開発中に、Sentinel GoコミュニティはKubernetesやService Meshなどのシナリオでいくつかの調査を行いました。

1、 KubernetesのCRDデータソース

本番環境では、コンフィグレーションセンターでルールの設定を動的に管理することができます。Kubernetesクラスタでは、当然Kubernetes CRDを使ってアプリケーションのSentinelルールを管理することができます。Go 1.0.0では、コミュニティがCRDを抽象化した基本的なSentinelルールと、それに対応するデータソースの実装を提供しています。ユーザーはSentinelにアクセスする際に、SentinelルールのCRD定義ファイルをインポートし、対応するデータソースを登録するだけで済みます。そして、CRDで定義されたフォーマットに基づいてYAML構成を記述し、対応する名前空間にkubectlを適用してルールを動的に構成する必要があります。以下は、フロー制御ルールの例です。

apiVersion: datasource.sentinel.io/v1alpha1
kind: FlowRules
metadata:
  name: foo-sentinel-flow-rules
spec:
  rules:
    - resource: simple-resource
      threshold: 500
    - resource: something-to-smooth
      threshold: 100
      controlBehavior: Throttling
      maxQueueingTimeMs: 500
    - resource: something-to-warmup
      threshold: 200
      tokenCalculateStrategy: WarmUp
      controlBehavior: Reject
      warmUpPeriodSec: 30
      warmUpColdFactor: 3

Kubernetes CRD data-source module link: https://github.com/sentinel-group/sentinel-go-datasource-k8s-crd

今後、コミュニティでは、CRDファイルの定義をさらに改善し、高可用性保護に関連する標準の抽象化について他のコミュニティと議論していきます。

2、サービスメッシュ

サービスメッシュは、クラウドネイティブ時代に進化するマイクロサービスのトレンドの一つです。サービスメッシュアーキテクチャの下では、一部のサービスガバナンスやポリシーコントロール機能が徐々にデータプレーン層に沈んでいきます。昨年、SentinelコミュニティはJava 1.7.0でいくつかの試みを行い、Envoyサービスメッシュにクラスタフロー制御機能を提供するために、Sentinel RLSトークンサーバの助けを借りてEnvoyグローバルレートリミッターgRPCサービスを提供しました。今年はSentinel Goの発売に伴い、コミュニティはより多くのサービスメッシュ製品との連携・統合を行いました。Ant FinancialのMOSNコミュニティと協力して、Sentinel Goのフローコントロール機能をMOSNメッシュで独自にサポートしており、Ant Financialでも実装されています。また、コミュニティはより一般的なソリューションを模索しています。例えば、コミュニティはIstioのEnvoy WebAssembly(WASM)拡張メカニズムを利用してSentinelプラグインを実装し、Istio/EnvoyサービスメッシュがSentinelのネイティブなフローコントロール機能と適応型保護機能を利用してクラスタサービス全体の安定性を確保できるようにしています。

3、 Sentinelメトリクスに基づくKubernetes HPA

サービスの安定性を確保するには、さまざまな方法があります。さまざまなルールでトラフィックを「制御」するだけでなく、「柔軟性」を持たせることも考えられます。Kubernetesにデプロイされたアプリケーションでは、Kubernetes HPAを使ってサービスを水平に拡張することができます。HPAはデフォルトで、複数のシステムメトリクスとカスタムメトリクスの統計情報をサポートしています。現時点では、Application High Availability Service(AHAS)SentinelとAlibaba Cloud Container Service for Kubernetesを組み合わせることで、サービスの平均QPSや応答時間に基づくオートスケーリングをサポートしています。この分野では、コミュニティもいくつかの試みを行っており、PrometheusやOpenTelemetryなどの標準的な方法でSentinelのサービスレベルのメトリクス(スループット、拒否されたトラフィック、応答時間など)を明らかにし、Kubernetes HPAに適応させています。

もちろん、Sentinelベースのエラスティックソリューションは万能ではありません。起動が速いServerlessサービスなど、一部の特定のシナリオにしか適用できません。起動が遅いサービスや、サービスの容量に影響されないシナリオでは、エラスティックソリューションは安定性の問題を解決できません。例えば、依存するデータベースの容量が不足している場合などです。エラスティックソリューションは、サービスの劣化を悪化させる可能性もあります。

ハッキングを始めよう

上記の高可用性保護のシナリオを学び、クラウド・ネイティブ分野におけるSentinelのいくつかの探索を終えて、マイクロサービスの耐障害性と安定性の方法について新たな理解が得られたと思います。ぜひ、マイクロサービスをSentinelに接続して、高可用性の保護と耐障害性を実現してください。これにより、サービスの安定性を保つことができます。同時に、Sentinel Go 1.0 GAのリリースは、コミュニティの貢献と切り離すことはできません。貢献に参加してくださったすべての方々に感謝します。

このバージョンの開発では、2人の新しいコミッター -- @ sanxu0325 と @ luckyxiaoqiang が、ウォームアップトラフィックのスロットルモード、Nacosの動的データソース、一連の機能改善とパフォーマンスの最適化をもたらしてくれました。彼らは、コミュニティの質問への回答やコードのレビューにとても積極的に協力してくれています。ありがとうございます。今後のバージョンでは、コミュニティはクラウドネイティブとアダプティブ・インテリジェントの方向性を探求し、進化させていきます。Sentinelの将来の進化に参加し、無限の可能性を生み出すために、誰でもコントリビューターグループに参加することができます。私たちは、以下を含む(ただしこれに限定されない)あらゆる形態の貢献を奨励します。

  • バグの修正
  • 新機能/改良点
  • ダッシュボード
  • ドキュメント/Webサイト
  • テストケース

開発者は、GitHub上の「good first issue list」から興味深い課題を選び、議論に参加して貢献することができます。積極的に貢献に参加していただいた開発者の方を中心に、コアな貢献者の方をコミッターとして推薦し、一緒にコミュニティの発展をリードしていきます。質問や提案は、GitHubのイシュー、Gitter、DingTalkグループ(グループ番号:30150716)を通じて交換していただくことができます。さあ、ハッキングを始めましょう

本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ