クラスタリング/セッションレプリケーション How-To

重要な注意事項

目次

急いでいる方へ

<Engine>または<Host>要素に

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

を追加してクラスタリングを有効にします。

上記の設定を使用すると、DeltaManagerを使用してセッションのデルタを複製するオールツーオールのセッションレプリケーションが有効になります。オールツーオールとは、すべてのセッションがクラスタ内の他のすべてのノードに複製されることを意味します。これは小規模なクラスタでは非常に効果的ですが、4ノードを超えるような大規模なクラスタにはお勧めしません。また、DeltaManagerを使用する場合、Tomcatはアプリケーションがデプロイされていないノードも含めてすべてのノードにセッションを複製します。
これらの問題を回避するには、BackupManagerを使用します。BackupManagerはセッションデータをバックアップノードの1つにのみ、そしてアプリケーションがデプロイされているノードのみに複製します。DeltaManagerを使用してシンプルなクラスタを実行したら、クラスタ内のノード数を増やすにつれて、BackupManagerに移行することをお勧めします。

重要なデフォルト値をいくつか示します。

  1. マルチキャストアドレスは228.0.0.4です。
  2. マルチキャストポートは45564です(ポートとアドレスを合わせてクラスタメンバーシップを決定します)。
  3. ブロードキャストされるIPアドレスはjava.net.InetAddress.getLocalHost().getHostAddress()です(127.0.0.1をブロードキャストしないようにしてください。これはよくある間違いです)。
  4. レプリケーションメッセージを待ち受けるTCPポートは、4000〜4100の範囲内の最初の使用可能なサーバーソケットです。
  5. リスナーはClusterSessionListenerとして設定されています。
  6. 2つのインターセプターTcpFailureDetectorMessageDispatchInterceptorが設定されています。

デフォルトのクラスタ設定を以下に示します。

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

このセクションについては、このドキュメントの後半で詳しく説明します。

セキュリティ

クラスタの実装は、すべてのクラスタ関連ネットワークトラフィックに安全で信頼できるネットワークが使用されていることを前提として記述されています。安全でない、信頼できないネットワークでクラスタを実行することは安全ではありません。

Tomcatクラスタで使用するための安全で信頼できるネットワークを提供するためのオプションは多数あります。これらには以下が含まれます。

  • プライベートLAN
  • 仮想プライベートネットワーク(VPN)
  • IPSEC

EncryptInterceptorは、機密性と整合性保護を提供しますが、信頼できないネットワークでTomcatクラスタを実行すること、特にDoS攻撃に関連するすべてのリスクから保護するものではありません。

クラスタの基本

Tomcat 10コンテナでセッションレプリケーションを実行するには、次の手順を実行する必要があります。

  • すべてのセッション属性はjava.io.Serializableを実装する必要があります。
  • server.xmlCluster要素のコメントを外します。
  • カスタムクラスタバルブを定義している場合、server.xmlのCluster要素の下にReplicationValveも定義されていることを確認してください。
  • Tomcatインスタンスが同じマシンで実行されている場合、各インスタンスのReceiver.port属性がユニークであることを確認してください。ほとんどの場合、Tomcatは4000〜4100の範囲で使用可能なポートを自動検出することで、これを独自に解決できます。
  • web.xml<distributable/>要素があることを確認してください。
  • mod_jkを使用している場合、Engineに<Engine name="Catalina" jvmRoute="node01" >でjvmRoute属性が設定され、jvmRoute属性値がworkers.propertiesのワーカー名と一致していることを確認してください。
  • すべてのノードの時刻が同じで、NTPサービスと同期していることを確認してください!
  • ロードバランサーがスティッキーセッションモードに設定されていることを確認してください。

ロードバランシングは、「ロードバランシング」の章で説明されているように、多くの手法で実現できます。

注:セッション状態はCookieによって追跡されるため、外部から見たURLが同じでなければ、新しいセッションが作成されます。

ClusterモジュールはTomcat JULIロギングフレームワークを使用するため、通常のlogging.propertiesファイルを使用してロギングを設定できます。メッセージを追跡するには、キーorg.apache.catalina.tribes.MESSAGESのロギングを有効にすることができます。

概要

Tomcatでセッションレプリケーションを有効にするには、まったく同じことを実現するために3つの異なる方法があります。

  1. セッションの永続化を使用し、セッションを共有ファイルシステムに保存する(PersistenceManager + FileStore)
  2. セッションの永続化を使用し、セッションを共有データベースに保存する(PersistenceManager + JDBCStore)
  3. Tomcatに付属のSimpleTcpCluster(lib/catalina-tribes.jar + lib/catalina-ha.jar)を使用して、インメモリレプリケーションを使用する

Tomcatは、DeltaManagerを使用してセッション状態のオールツーオールレプリケーションを実行するか、BackupManagerを使用して1つのノードのみにバックアップレプリケーションを実行できます。オールツーオールレプリケーションは、クラスタが小さい場合にのみ効率的なアルゴリズムです。大規模なクラスタの場合は、プライマリセカンダリのセッションレプリケーション戦略を使用するBackupManagerを使用する必要があります。この戦略では、セッションは1つのバックアップノードのみに保存されます。
現在、ドメインワーカー属性(mod_jk > 1.2.8)を使用してクラスタパーティションを構築し、DeltaManagerでよりスケーラブルなクラスタソリューションを実現できます(これにはドメインインターセプターを設定する必要があります)。オールツーオール環境でのネットワークトラフィックを削減するために、クラスタを小さなグループに分割できます。これは、異なるグループに異なるマルチキャストアドレスを使用することで簡単に実現できます。非常に簡単な設定は次のようになります。

        DNS Round Robin
               |
         Load Balancer
          /           \
      Cluster1      Cluster2
      /     \        /     \
  Tomcat1 Tomcat2  Tomcat3 Tomcat4

ここで重要なのは、セッションレプリケーションはクラスタリングの始まりに過ぎないということです。クラスタを実装するために使用されるもう1つの一般的な概念はファームであり、つまり、アプリケーションを1つのサーバーのみにデプロイし、クラスタ全体でデプロイメントを分散します。これらはすべて、FarmWarDeployer(server.xmlのクラスタ例を参照)で使用できる機能です。

次のセクションでは、セッションレプリケーションの動作と設定方法について詳しく説明します。

クラスタ情報

メンバーシップはマルチキャストハートビートを使用して確立されます。したがって、クラスタを細分化したい場合は、<Membership>要素のマルチキャストIPアドレスまたはポートを変更することで実行できます。

ハートビートには、TomcatノードのIPアドレスと、TomcatがレプリケーショントラフィックをリッスンするTCPポートが含まれています。すべてのデータ通信はTCPを介して行われます。

ReplicationValveは、リクエストが完了した時点を検出し、レプリケーションを開始するために使用されます(もしあれば)。セッションが変更された場合(セッションに対してsetAttributeまたはremoveAttributeを呼び出す場合)のみ、データが複製されます。

最も重要なパフォーマンス上の考慮事項の1つは、同期レプリケーションと非同期レプリケーションです。同期レプリケーションモードでは、複製されたセッションがワイヤを介して送信され、他のすべてのクラスタノードで再インスタンス化されるまで、リクエストは返されません。同期と非同期はchannelSendOptionsフラグを使用して設定され、整数値です。SimpleTcpCluster/DeltaManagerの組み合わせのデフォルト値は8(非同期)です。さまざまなchannelSendOptions値の詳細については、設定リファレンスを参照してください。

便宜上、channelSendOptionsは整数ではなく名前で設定できます。名前は、起動時に整数値に変換されます。有効なオプション名は、「asynchronous」(エイリアス「async」)、「byte_message」(エイリアス「byte」)、「multicast」、「secure」、「synchronized_ack」(エイリアス「sync」)、「udp」、「use_ack」です。複数の名前を区切るにはカンマを使用します。たとえば、「async, multicast」を渡すと、オプションSEND_OPTIONS_ASYNCHRONOUS | SEND_OPTIONS_MULTICASTになります。

送信フラグ(概要)または送信フラグ(Javadoc)で詳細を読むことができます。非同期レプリケーションでは、データが複製される前にリクエストが返されます。非同期レプリケーションによりリクエスト時間が短縮され、同期レプリケーションにより、リクエストが返される前にセッションが複製されることが保証されます。

クラッシュ後にフェイルオーバーノードにセッションをバインドする

mod_jkを使用していて、スティッキーセッションを使用していない場合、または何らかの理由でスティッキーセッションが機能しない場合、または単にフェイルオーバーしている場合、セッションIDは変更する必要があります。これは、以前は前のTomcatのワーカーID(Engine要素のjvmRouteで定義)が含まれていたためです。これを解決するために、JvmRouteBinderValveを使用します。

JvmRouteBinderValveはセッションIDを書き換え、フェイルオーバー後も次のリクエストがスティッキーな状態を維持することを保証します(ワーカーが使用できなくなったため、ランダムなノードにフォールバックしません)。このバルブは、Cookie内のJSESSIONID値を同じ名前で書き換えます。このバルブがないと、mod_jkモジュールの場合、障害発生時のスティッキネスを保証することが困難になります。

server.xmlに独自のバルブを追加する場合は、デフォルトが無効になるため、デフォルトで定義されているすべての適切なバルブを追加してください。

ヒント
属性sessionIdAttributeを使用して、古いセッションIDが含まれるリクエスト属性名を変更できます。デフォルトの属性名はorg.apache.catalina.ha.session.JvmRouteOriginalSessionIDです。

コツ
ノードを削除する前に、JMXを使用してこのmod_jkターンオーバーモードをすべてのバックアップノードで有効にすることができます!すべてのJvmRouteBinderValveバックアップでenableをtrueに設定し、mod_jkでワーカーを無効にしてから、ノードを削除して再起動します!その後、mod_jkワーカーを有効にし、JvmRouteBinderValvesを再度無効にします。このユースケースは、要求されたセッションのみが移行されることを意味します。

設定例

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

          <Manager className="org.apache.catalina.ha.session.BackupManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>
          <!--
          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
          -->
          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="5000"
                      selectorTimeout="100"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

詳細に分解する!!

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

この要素内には、すべてのクラスタの詳細を設定できます。channelSendOptionsは、SimpleTcpClusterクラスまたはSimpleTcpCluster.sendメソッドを呼び出すオブジェクトによって送信される各メッセージに添付されるフラグです。送信フラグの説明は、Javadocサイトをご覧ください。DeltaManagerはSimpleTcpCluster.sendメソッドを使用して情報を送信しますが、バックアップマネージャはチャネルを介して直接送信します。
詳細については、参考ドキュメントをご覧ください。

          <Manager className="org.apache.catalina.ha.session.BackupManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"
                   mapSendOptions="6"/>
          <!--
          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
          -->

これは、``要素でマネージャが定義されていない場合に使用されるマネージャ構成のテンプレートです。Tomcat 5.xでは、分散可能とマークされた各Webアプリケーションは同じマネージャを使用する必要がありましたが、Tomcatでは各Webアプリケーションにマネージャクラスを定義できるため、クラスタ内でマネージャを混在させることができます。明らかに、あるノードのアプリケーション上のマネージャは、他のノードの同じアプリケーション上の同じマネージャに対応する必要があります。Webアプリケーションに対してマネージャが指定されておらず、Webアプリケーションが``とマークされている場合、Tomcatはこのマネージャ構成を使用して、この構成を複製したマネージャインスタンスを作成します。
詳細については、参考ドキュメントをご覧ください。

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">

チャネル要素はTribesであり、Tomcatで使用されるグループ通信フレームワークです。この要素は、通信とメンバーシップロジックに関するすべてをカプセル化します。
詳細については、参考ドキュメントをご覧ください。

            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>

メンバーシップはマルチキャストを使用して行われます。マルチキャストを超えるポイントにメンバーシップを拡張したい場合は、TribesはStaticMembershipInterceptorを使用した静的メンバーシップもサポートすることに注意してください。address属性は使用されるマルチキャストアドレスであり、portはマルチキャストポートです。これら2つを組み合わせることで、クラスタの分離が実現されます。QAクラスタと本番クラスタが必要な場合は、QAクラスタを本番クラスタとは異なるマルチキャストアドレス/ポートの組み合わせにするのが最も簡単な構成です。
メンバーシップコンポーネントは、ノード間の通信がTCPを介して行えるように、自身のTCPアドレス/ポートを他のノードにブロードキャストします。ブロードキャストされるアドレスはReceiver.address属性のアドレスであることに注意してください。
詳細については、参考ドキュメントをご覧ください。

            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="5000"
                      selectorTimeout="100"
                      maxThreads="6"/>

Tribesでは、データの送受信ロジックが2つの機能コンポーネントに分割されています。名前が示すように、Receiverはメッセージの受信を担当します。Tribesスタックはスレッドレスであるため(現在他のフレームワークでも採用されている一般的な改善点)、このコンポーネントには、maxThreadsとminThreadsの設定を持つスレッドプールがあります。
address属性は、メンバーシップコンポーネントによって他のノードにブロードキャストされるホストアドレスです。
詳細については、参考ドキュメントをご覧ください。

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>

Senderコンポーネントは、名前が示すように、他のノードへのメッセージ送信を担当します。SenderにはReplicationTransmitterというシェルコンポーネントがありますが、実際の処理はサブコンポーネントTransportで行われます。TribesはSenderのプールを持つことをサポートしているため、メッセージを並列に送信できます。NIO Senderを使用している場合は、メッセージを同時に送信することもできます。
同時とは、複数のSenderに同時に1つのメッセージを送信することを意味し、並列とは、複数のSenderに同時に複数のメッセージを送信することを意味します。
詳細については、参考ドキュメントをご覧ください。

            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
          </Channel>

Tribesは、メッセージを送信するためにスタックを使用します。スタックの各要素はインターセプタと呼ばれ、Tomcatサーブレットコンテナのバルブと同様に機能します。インターセプタを使用すると、ロジックをより管理しやすいコードの断片に分割できます。上記で構成されたインターセプタは次のとおりです。
TcpFailureDetector - TCPを介してクラッシュしたメンバーを検証します。マルチキャストパケットがドロップされた場合、このインターセプタは誤検知を防ぎます(つまり、ノードはまだ稼働しているにもかかわらず、クラッシュしたとマークされます)。
MessageDispatchInterceptor - メッセージをスレッド(スレッドプール)にディスパッチして、非同期的にメッセージを送信します。
ThroughputInterceptor - メッセージトラフィックに関する簡単な統計情報を表示します。
インターセプタの順序は重要であることに注意してください。server.xmlで定義されている順序が、チャネルスタックで表される順序です。これを、ヘッドが最初のインターセプタで、テールが最後のインターセプタであるリンクリストと考えてください。
詳細については、参考ドキュメントをご覧ください。

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

クラスタはバルブを使用してWebアプリケーションへのリクエストを追跡します。上記ではReplicationValveとJvmRouteBinderValveについて説明しました。``要素自体はTomcatのパイプラインの一部ではありません。代わりに、クラスタはバルブを親コンテナに追加します。``要素が``要素で構成されている場合、バルブはエンジンに追加されます。
詳細については、参考ドキュメントをご覧ください。

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

デフォルトのTomcatクラスタはファームドデプロイメントをサポートしています。つまり、クラスタは他のノードにアプリケーションをデプロイおよびアンデプロイできます。このコンポーネントの状態は現在変動していますが、すぐに対応されます。Tomcat 5.0と5.5の間でデプロイメントアルゴリズムに変更があり、その時点でこのコンポーネントのロジックが変更され、デプロイディレクトリがwebappsディレクトリと一致する必要があります。
詳細については、参考ドキュメントをご覧ください。

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>

SimpleTcpCluster自体はChannelオブジェクトのSenderとReceiverであるため、コンポーネントはSimpleTcpClusterにリスナーとして自身を登録できます。上記のリスナーClusterSessionListenerはDeltaManagerレプリケーションメッセージをリスンし、デルタをマネージャに適用します。マネージャはそれをセッションに適用します。
詳細については、参考ドキュメントをご覧ください。

クラスタアーキテクチャ

コンポーネントレベル

         Server
           |
         Service
           |
         Engine
           |  \
           |  --- Cluster --*
           |
         Host
           |
         ------
        /      \
     Cluster    Context(1-N)
        |             \
        |             -- Manager
        |                   \
        |                   -- DeltaManager
        |                   -- BackupManager
        |
     ---------------------------
        |                       \
      Channel                    \
    ----------------------------- \
        |                          \
     Interceptor_1 ..               \
        |                            \
     Interceptor_N                    \
    -----------------------------      \
     |          |         |             \
   Receiver    Sender   Membership       \
                                         -- Valve
                                         |      \
                                         |       -- ReplicationValve
                                         |       -- JvmRouteBinderValve
                                         |
                                         -- LifecycleListener
                                         |
                                         -- ClusterListener
                                         |      \
                                         |       -- ClusterSessionListener
                                         |
                                         -- Deployer
                                                \
                                                 -- FarmWarDeployer

動作原理

クラスタリングの仕組みを理解しやすくするために、いくつかのシナリオについて説明します。このシナリオでは、TomcatATomcatBの2つのTomcatインスタンスのみを使用することを計画しています。次のイベントシーケンスについて説明します。

  1. TomcatAが起動します。
  2. TomcatBが起動します(TomcatAの起動が完了するのを待ちます)。
  3. TomcatAがリクエストを受信し、セッションS1が作成されます。
  4. TomcatAがクラッシュします。
  5. TomcatBがセッションS1のリクエストを受信します。
  6. TomcatAが起動します。
  7. TomcatAがリクエストを受信し、セッション(S1)に対して無効化が呼び出されます。
  8. TomcatBが新しいセッション(S2)のリクエストを受信します。
  9. TomcatAで、セッションS2が非アクティブのために期限切れになります。

さて、良いシーケンスができたので、セッションレプリケーションコードで実際に何が起こるかを説明します。

  1. TomcatAが起動します。

    Tomcatは標準的な起動シーケンスを使用して起動します。Hostオブジェクトが作成されると、クラスタオブジェクトがそれに関連付けられます。コンテキストが解析されると、web.xmlファイルにdistributable要素が存在する場合、Tomcatはクラスタクラス(この場合はSimpleTcpCluster)に、レプリケートされたコンテキストのマネージャの作成を要求します。したがって、クラスタリングが有効になり、web.xmlにdistributableが設定されていると、TomcatはStandardManagerではなく、そのコンテキストにDeltaManagerを作成します。クラスタクラスは、メンバーシップサービス(マルチキャスト)とレプリケーションサービス(TCPユニキャスト)を起動します。このドキュメントのさらに下にあるアーキテクチャの詳細については、後で説明します。

  2. TomcatBが起動します。

    TomcatBが起動すると、1つの例外を除いて、TomcatAと同じシーケンスに従います。クラスタが起動し、メンバーシップ(TomcatATomcatB)が確立されます。TomcatBは、クラスタに既に存在するサーバー(この場合はTomcatA)からセッションの状態を要求します。TomcatAはリクエストに応答し、TomcatBがHTTPリクエストのリスンを開始する前に、状態がTomcatAからTomcatBに転送されます。TomcatAが応答しない場合、TomcatBは60秒後にタイムアウトし、ログエントリを出力して起動を続けます。セッションの状態は、web.xmlにdistributableがある各Webアプリケーションについて転送されます。(注:セッションレプリケーションを効率的に使用するには、すべてのTomcatインスタンスを同じように構成する必要があります)。

  3. TomcatAがリクエストを受信し、セッションS1が作成されます。

    TomcatAに入ってきたリクエストは、セッションレプリケーションがない場合とまったく同じように処理されます。リクエストが完了するまで、その時点でReplicationValveがレスポンスがユーザーに返される前にリクエストをインターセプトします。この時点で、セッションが変更されたことが判明し、TCPを使用してセッションをTomcatBにレプリケートします。シリアル化されたデータがオペレーティングシステムのTCPロジックに渡されると、リクエストはバルブパイプラインを介してユーザーに戻ります。各リクエストに対してセッション全体がレプリケートされるため、setAttributeまたはremoveAttributeを呼び出さずにセッション内の属性を変更するコードもレプリケートされます。useDirtyFlag構成パラメータを使用して、セッションがレプリケートされる回数を最適化できます。

  4. TomcatAがクラッシュします。

    TomcatAがクラッシュすると、TomcatBTomcatAがクラスタから脱落したことを通知されます。TomcatBはメンバーシップリストからTomcatAを削除し、TomcatAにはTomcatBで発生する変更は通知されなくなります。ロードバランサはTomcatAからのリクエストをTomcatBにリダイレクトし、すべてのセッションは最新の状態になります。

  5. TomcatBがセッションS1のリクエストを受信します。

    特に何もありません。TomcatBはリクエストを他のリクエストと同じように処理します。

  6. TomcatAが起動します。

    起動時に、TomcatAが新しいリクエストを受け入れ、利用可能になる前に、上記1)2)で説明した起動シーケンスに従います。クラスタに参加し、TomcatBにすべてのセッションの現在の状態を要求します。セッションの状態を受信すると、ロードが完了し、HTTP/mod_jkポートが開きます。したがって、TomcatBからセッションの状態を受信するまで、TomcatAにリクエストは届きません。

  7. TomcatAがリクエストを受信し、セッション(S1)に対して無効化が呼び出されます。

    無効化呼び出しがインターセプトされ、セッションが無効化されたセッションにキューイングされます。リクエストが完了すると、変更されたセッションを送信する代わりに、TomcatBに「期限切れ」メッセージを送信し、TomcatBもセッションを無効化します。

  8. TomcatBが新しいセッション(S2)のリクエストを受信します。

    ステップ3)と同じシナリオです。

  9. TomcatAで、セッションS2が非アクティブのために期限切れになります。

    無効化呼び出しは、ユーザーによってセッションが無効化された場合と同じようにインターセプトされ、セッションは無効化されたセッションにキューイングされます。この時点で、無効化されたセッションは、別のリクエストがシステムを通過して無効キューをチェックするまで、レプリケートされません。

ふぅ!(完了しました)

メンバーシップクラスタメンバーシップは、非常に単純なマルチキャストpingを使用して確立されます。各Tomcatインスタンスは定期的にマルチキャストpingを送信し、pingメッセージでインスタンスはレプリケーション用のIPとTCPリスンポートをブロードキャストします。インスタンスが指定された時間内にそのようなpingを受信しなかった場合、メンバーは死んでいると見なされます。非常にシンプルで、非常に効果的です!もちろん、システムでマルチキャストを有効にする必要があります。

TCPレプリケーションマルチキャストpingを受信すると、メンバーはクラスタに追加されます。次のレプリケーションリクエストで、送信インスタンスはホストとポート情報を使用してTCPソケットを確立します。このソケットを使用して、シリアル化されたデータを送信します。TCPソケットを選択した理由は、フロー制御と配信保証が組み込まれているためです。そのため、データを送信すると、確実に届きます。

分散ロックとフレームを使用したページ Tomcatは、クラスタ全体でセッションインスタンスを同期しません。このようなロジックの実装はオーバーヘッドが大きすぎ、様々な問題を引き起こします。クライアントが複数のリクエストを使用して同時に同じセッションにアクセスした場合、最後のリクエストがクラスタ内の他のセッションを上書きします。

JMXを使用したクラスタの監視

クラスタを使用する場合、モニタリングは非常に重要な問題です。クラスタオブジェクトの一部はJMX MBeanです。

起動スクリプトに以下のパラメータを追加してください。

set CATALINA_OPTS=\
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=%my.jmx.port% \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false

クラスタMBean一覧

名称 説明 MBean ObjectName - エンジン MBean ObjectName - ホスト
クラスタ 完全なクラスタ要素 type=Cluster type=Cluster,host=${HOST}
DeltaManager このマネージャはセッションを制御し、セッションレプリケーションを処理します。 type=Manager,context=${APP.CONTEXT.PATH}, host=${HOST} type=Manager,context=${APP.CONTEXT.PATH}, host=${HOST}
FarmWarDeployer クラスタ内のすべてのノードへのアプリケーションのデプロイプロセスを管理します。 サポートされていません。 type=Cluster, host=${HOST}, component=deployer
メンバー クラスタ内のノードを表します。 type=Cluster, component=member, name=${NODE_NAME} type=Cluster, host=${HOST}, component=member, name=${NODE_NAME}
ReplicationValve このバルブは、バックアップノードへのレプリケーションを制御します。 type=Valve,name=ReplicationValve type=Valve,name=ReplicationValve,host=${HOST}
JvmRouteBinderValve これは、セッションIDを現在のTomcat jvmrouteに変更するためのクラスタフォールバックバルブです。 type=Valve,name=JvmRouteBinderValve, context=${APP.CONTEXT.PATH} type=Valve,name=JvmRouteBinderValve,host=${HOST}, context=${APP.CONTEXT.PATH}

FAQ

詳細は、FAQのクラスタリングセクションを参照してください。