クラスタリング/セッションレプリケーションのハウツー

重要事項

設定リファレンスドキュメントも参照できます。

目次

手っ取り早く知りたい方へ

単に以下を追加するだけです

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

クラスタリングを有効にするには、<Engine> または <Host> 要素に。

上記の構成を使用すると、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 11 コンテナでセッションレプリケーションを実行するには、以下の手順を完了する必要があります

  • すべてのセッション属性は java.io.Serializable を実装する必要があります
  • server.xml 内の Cluster 要素のコメントを解除します
  • カスタムクラスターバルブを定義している場合は、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サービスと同期していることを確認してください!
  • ロードバランサーがスティッキーセッションモード用に設定されていることを確認してください。

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

注: セッションの状態はクッキーによって追跡されるため、URLは外部から見て同じである必要があります。そうでない場合、新しいセッションが作成されます。

クラスターモジュールは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つのノードにのみバックアップレプリケーションを実行できます。オールツーオールレプリケーションは、クラスターが小規模な場合にのみ効率的なアルゴリズムです。大規模なクラスターでは、セッションが1つのバックアップノードにのみ保存されるプライマリ-セカンダリセッションレプリケーション戦略を使用するために BackupManager を使用する必要があります。
現在、ドメインワーカー属性 (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」です。複数の名前をコンマで区切って使用します。例えば、オプション SEND_OPTIONS_ASYNCHRONOUS | SEND_OPTIONS_MULTICAST の場合は「async, multicast」を渡します。

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

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

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

JvmRouteBinderValve はセッションIDを書き換えることで、フェールオーバー後も次のリクエストがスティッキーであり続ける (ワーカーが利用できなくなったため、ランダムなノードにフォールバックしない) ことを保証します。このバルブは、同名のクッキー内の JSESSIONID の値を書き換えます。このバルブが配置されていない場合、mod_jk モジュールの障害発生時にスティッキー性を確保することが難しくなります。

注意してください。server.xml で独自のバルブを追加する場合、デフォルトはもはや有効ではありません。デフォルトで定義されているすべての適切なバルブを追加していることを確認してください。

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

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

設定例

        <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"/>
          -->

これは、<Context> 要素にマネージャーが定義されていない場合に使用されるマネージャー設定のテンプレートです。Tomcat 5.x では、distributable とマークされた各 Web アプリケーションは同じマネージャーを使用する必要がありましたが、Tomcat 以降は各 Web アプリケーションにマネージャーを定義できるため、クラスター内でマネージャーを混在させることができます。当然ながら、あるノードのアプリケーション上のマネージャーは、別のノードの同じアプリケーション上の同じマネージャーに対応している必要があります。Web アプリケーションにマネージャーが指定されておらず、Web アプリケーションが <distributable/> とマークされている場合、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 は送信者のプールを持つことをサポートしているため、メッセージを並行して送信でき、NIO 送信者を使用している場合は同時にメッセージを送信することもできます。
「Concurrently(同時)」とは、1つのメッセージを複数の送信者に同時に送信することを意味し、「Parallel(並行)」とは、複数のメッセージを複数の送信者に同時に送信することを意味します。
詳細については、リファレンスドキュメントをご覧ください

            <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 について言及しました。<Cluster> 要素自体は Tomcat のパイプラインの一部ではありません。代わりに、クラスターはバルブをその親コンテナに追加します。<Cluster> 要素が <Engine> 要素に設定されている場合、バルブはエンジンに追加されます。
詳細については、リファレンスドキュメントをご覧ください

          <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 オブジェクトの送信者および受信者であるため、コンポーネントは 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) で invalidate が呼び出される
  8. TomcatB が新しいセッション (S2) のリクエストを受け取る
  9. TomcatA のセッション S2 が非アクティブにより期限切れになる。

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

  1. TomcatA が起動する

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

  2. TomcatB が起動する

    TomcatB が起動すると、TomcatA と同じシーケンスに従いますが、1つの例外があります。クラスターが起動され、メンバーシップ (TomcatA、TomcatB) が確立されます。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 がクラッシュすると、TomcatB は TomcatA がクラスターから脱落したという通知を受け取ります。TomcatB は TomcatA をメンバーシップリストから削除し、TomcatA は TomcatB で発生するいかなる変更も通知されなくなります。ロードバランサーは TomcatA から TomcatB へリクエストをリダイレクトし、すべてのセッションは最新の状態になります。

  5. TomcatB がセッション S1 のリクエストを受け取る

    特に注目すべきことはなく、TomcatB は他のリクエストと同様にリクエストを処理します。

  6. TomcatA が起動する

    起動時、TomcatA が新しいリクエストを受け付け、自身を利用可能にする前に、上記の起動シーケンス1) 2) に従います。クラスターに参加し、TomcatB にすべてのセッションの現在の状態を問い合わせます。そしてセッション状態を受信すると、ロードを完了し、HTTP/mod_jk ポートを開きます。したがって、TomcatA が TomcatB からセッション状態を受信するまで、いかなるリクエストも TomcatA に到達することはありません。

  7. TomcatA がリクエストを受け取り、セッション (S1) で invalidate が呼び出される

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

  8. TomcatB が新しいセッション (S2) のリクエストを受け取る

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

  9. TomcatA のセッション S2 が非アクティブにより期限切れになる。

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

ふぅー! :)

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

TCP レプリケーション マルチキャストピングが受信されると、そのメンバーはクラスターに追加されます。次のレプリケーションリクエスト時に、送信元のインスタンスはホストとポートの情報を使用して 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 - Engine MBean ObjectName - Host
Cluster 完全なクラスター要素 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のクラスタリングセクションを参照してください。