InfinispanとJGroupsにおける障害検出の理解

このガイドでは、JGroupsが障害インスタンスをどのように検出するか、およびその設定方法について説明します。また、カスタマイズ可能な構成属性と、目的の検出率を達成するためのトレードオフについて説明します。

JGroupsが使用される場所と、障害検出が重要な理由

Keycloakは、Keycloak内部と外部のInfinispanインスタンスの両方で、分散キャッシュにセッション関連情報を格納するためにInfinispanを使用します。Keycloakインスタンスと外部Infinispanインスタンスはクラスターを形成し、クラスターのノード間の通信はJGroupsによって処理されます。マルチサイトセットアップにおける異なる外部Infinispanクラスター間の通信もJGroupsによって処理されます。

そのようなクラスター内の各ノードは、Keycloakがリクエストを処理するために重要なセッションデータを提供しています。応答のないノードは、リクエストのブロック、および場合によっては呼び出し元側のタイムアウトとエラーにつながります。ノードが失敗した場合、リクエストは残りのノードにリダイレクトする必要があり、そのデータはクラスター内のバックアップノードから再配布する必要があります。

通信障害を引き起こすTCP接続の切断

切断されたTCP接続はクラスターのパフォーマンスに影響を与え、接続を閉じて新しい接続を確立できるように、それを検出する必要があります。TCPはブロッキング/同期プロトコルであり、接続が正常に機能していない場合、スレッドはSocket::write操作でブロックされることに注意してください。カーネルパラメータtcp_retries2は、カーネルが強制的に接続を閉じるまでの失敗した再試行回数を設定します。カーネルドキュメントからの引用:

この値は、RTO再送信が確認応答されない場合、アクティブなTCP接続のタイムアウトに影響を与えます。デフォルト値の15は、924.6秒の仮想タイムアウトをもたらし、有効タイムアウトの下限です。

この期間中、クラスターのパフォーマンスは低下します。イメージまたはコンテナ内のカーネルパラメータを変更することは望ましくありませんが、JGroupsには、これらの切断された接続を検出して強制的に閉じるように構成できる属性があります。

KubernetesでTUNNELプロトコルを使用するクロスサイトネットワーク通信の場合、Infinispan PodトラフィックはJGroups Gossip Router Podを介して転送されます。タイムアウトは、以下に示すようにInfinispan CR YAMLファイルで構成されています。

infinispan.yaml
  service:
    type: DataGrid
    sites:
      local:
        discovery:
          heartbeats:
            interval: 10000 (1)
            timeout: 30000 (2)
1 intervalミリ秒ごとにGossipルーターにハートビートを送信します。
2 メッセージまたはハートビートを受信してからGossipルーターへの接続が閉じられるまでの最大時間(ミリ秒)。
上記の値は、Infinispan Operatorによって構成されたデフォルト値です。

間隔とタイムアウトを短縮すると、JGroupsが切断された接続を検出する速度が向上します。ただし、ハートビートの頻度が増加するため、ネットワーク使用量も増加します。両方のクラスター内のすべてのInfinispan Podが、構成されたすべてのGossip Router Podにハートビートを送信することに注意してください。

デフォルトは、ユースケースの99%で機能するはずです。

InfinispanまたはKeycloakクラスター内のクラスタ内通信の場合、切断されたTCP接続は障害検出によって検出および閉じられます。詳細については、セクション応答のないノードの検出を参照してください。

応答のないノードの検出

クラスター内のノードは失敗する可能性があり、それが起こるとトラフィックとデータをリダイレクトする必要があります。JGroupsの障害検出は、Infinispanに同梱されているデフォルトのJGroups構成に存在するプロトコルFD_ALL3によって提供されます。

FD_ALL3は、すべてのメンバーが定期的にハートビートをマルチキャストするシンプルなハートビートプロトコルです。別のPodからのデータまたはハートビートが受信されると、そのPodはアクティブと見なされます。それ以外の場合、Podは疑わしいと見なされ、グループビューから削除される可能性があります。

ハートビートの間隔とタイムアウトは、次のように構成されています。

<infinispan>
   <jgroups>
      <stack name="my-tcp" extends="tcp"> (1)
         <FD_ALL3 stack.combine="COMBINE"
               interval="8000" (2)
               timeout="40000"/> (3)
      </stack>
   </jgroups>

   <cache-container>
      <transport stack="my-tcp"/> (4)
   </cache-container>
</infinispan>
1 カスタムスタック名。
2 クラスターにハートビートが送信される間隔(ミリ秒)。
3 ノードからハートビートもデータも受信されなかった場合に、ノードが疑わしいと見なされるまでのタイムアウト(ミリ秒)。
4 JGroupsで使用されるスタック名。
上記の例は、デフォルト値を示しています。

M個のPodのクラスターの場合、各Podは各間隔でM-1個のハートビートメッセージを生成します。intervaltimeoutを短縮すると、クラッシュしたPodの検出速度が向上しますが、余分なメッセージが送信されるため、ネットワークへの影響が大きくなります。

クロスサイトが有効になっている場合、FD_ALL3ハートビートはリモートクラスターにも流れます。クロスサイトチャネルには、クラスタ内通信とは独立して構成できる独自の構成があります。

デフォルトは、ユースケースの99%で機能するはずです。

Podが疑わしいと判断されると、クラッシュしたメンバーなしで新しいグループビューの変更がトリガーされます。このイベントは、そのPodとの切断されたTCP接続を閉じ、ブロックされている可能性のあるスレッドをブロック解除します。

読み取りおよび書き込み操作のタイムアウト

Infinispanには、KeycloakとInfinispanクラスターの両方で、読み取りまたは書き込み操作に影響を与える3つの構成可能なタイムアウトがあります。それらは、ロックタイムアウト、リモートタイムアウト、およびクロスサイトリモートタイムアウトです。

タイムアウトが互いに、および上記の障害検出タイムアウトと間隔と一致している場合、接続またはノードの障害後に少なくとも1回の再試行が許可されます。これにより、呼び出し元に有効な応答を提供し、発生したエラーを隠蔽することができます。

ロックタイムアウトは、操作がロックが解放されるのを待つ待機時間です。これはすべての中で最小である必要があります。

リモートタイムアウトは、Infinispan Podが同じクラスター内の他のPodからの応答を待つ時間です。データのレプリケーション時の書き込みと、コピーがローカルに存在しない場合にPodが他のPodからデータをフェッチする読み取りの両方に影響します。

最後に、マルチサイトデプロイメントの場合、クロスサイトリモートタイムアウトは、他のクラスターが更新を承認するまでの待機時間です。

これらの値を変更すると、応答時間に直接的な影響を与える可能性があります。通常動作中、Infinispanは数ミリ秒で応答しますが、ワークロードが高い場合、Podがクラッシュした場合、またはネットワーク停止が発生した場合、これらのタイムアウトに達する可能性があります。

タイムアウトを短縮すると、応答時間が短縮されます。Infinispanはより早く諦めますが、ユーザーに報告されるエラー率が増加します。これらの値を増やすと、Infinispanがワークロードを処理する時間が増えるため、エラーの量を減らすことができますが、エンドユーザーが観察する応答時間は長くなります。

Infinispan OperatorでデプロイされたInfinispanクラスターでタイムアウト値を更新するには、次のようにCacheCRを更新します。

apiVersion: infinispan.org/v2alpha1
kind: Cache
metadata:
  name: sessions
spec:
  clusterName: infinispan
  name: sessions
  template: |-
    distributedCache:
      mode: "SYNC"
      owners: 2
      statistics: "true"
      remoteTimeout: "15000" (1)
      locking:
        acquireTimeout: "10000" (2)
      backups:
        cluster-b:
          backup:
            strategy: "SYNC"
            timeout: "15000"  (3)
1 ローカルクラスター内の他のPodからの応答を待つタイムアウト値(ミリ秒)。
2 ロックされたロックが解放されるのを待つタイムアウト値(ミリ秒)。
3 リモートクラスターからの応答を待つタイムアウト値(ミリ秒)。
この例はデフォルト値を示しています。更新するタイムアウトの行のみを追加してください。

Keycloakサーバーで実行されているInfinispanクラスターの場合、カスタマイズされたInfinispan XMLファイルが必要です。表示されているようにキャッシュ構成を変更し、更新する属性(太字)を追加します。

<distributed-cache name="sessions" owners="2" statistics="true" remote-timeout="15000"> (1)
    <locking acquire-timeout="10000"/> (2)
    <backups>
        <backup site="cluster-b" timeout="15000"/> (3)
    </backups>
</distributed-cache>
1 ローカルクラスター内の他のPodからの応答を待つタイムアウト値(ミリ秒)。
2 ロックされたロックが解放されるのを待つタイムアウト値(ミリ秒)。
3 リモートクラスターからの応答を待つタイムアウト値(ミリ秒)。
この例はデフォルト値を示しています。