クラスタリング/セッションレプリケーションのハウツー
重要事項
目次
手っ取り早く知りたい方へ
単に以下を追加するだけです
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
クラスタリングを有効にするには、<Engine>
または <Host>
要素に。
上記の構成を使用すると、DeltaManager
を使用してセッションの差分をレプリケートする、オールツーオールセッションレプリケーションが有効になります。オールツーオールとは、クラスター内のすべてのセッションが他のすべてのノードにレプリケートされることを意味します。これは小規模なクラスターには非常に効果的ですが、4ノードを超えるような大規模なクラスターにはお勧めしません。また、DeltaManager を使用する場合、Tomcat は、アプリケーションがデプロイされていないノードでさえも、すべてのノードにセッションをレプリケートします。
これらの問題を回避するには、BackupManager
を使用することをお勧めします。BackupManager
は、セッションデータを1つのバックアップノードにのみ、かつアプリケーションがデプロイされているノードにのみレプリケートします。DeltaManager
で単純なクラスターが動作し始めたら、クラスター内のノード数を増やすにつれて、おそらく BackupManager
に移行したいと思うでしょう。
重要なデフォルト値をいくつか示します
- マルチキャストアドレスは 228.0.0.4
- マルチキャストポートは 45564 (ポートとアドレスの組み合わせでクラスターメンバーシップが決まります)。
- ブロードキャストされるIPは
java.net.InetAddress.getLocalHost().getHostAddress()
です (127.0.0.1 をブロードキャストしないように注意してください。これは一般的なエラーです) - レプリケーションメッセージをリッスンするTCPポートは、範囲
4000-4100
で最初に使用可能なサーバーソケットです - リスナーは
ClusterSessionListener
が設定されています - 2つのインターセプター
TcpFailureDetector
とMessageDispatchInterceptor
が設定されています
以下はデフォルトのクラスター構成です
<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つの異なる方法があります
- セッション永続化を使用し、セッションを共有ファイルシステムに保存する (PersistenceManager + FileStore)
- セッション永続化を使用し、セッションを共有データベースに保存する (PersistenceManager + JDBCStore)
- 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
仕組み
クラスタリングの仕組みを分かりやすくするために、一連のシナリオを通じて説明します。このシナリオでは、TomcatA
と TomcatB
の2つの Tomcat インスタンスのみを使用する予定です。以下のイベントシーケンスを扱います。
TomcatA
が起動するTomcatB
が起動する (TomcatA の起動が完了するまで待つ)TomcatA
がリクエストを受け取り、セッションS1
が作成される。TomcatA
がクラッシュするTomcatB
がセッションS1
のリクエストを受け取るTomcatA
が起動するTomcatA
がリクエストを受け取り、セッション (S1
) で invalidate が呼び出されるTomcatB
が新しいセッション (S2
) のリクエストを受け取るTomcatA
のセッションS2
が非アクティブにより期限切れになる。
さて、良いシーケンスができたところで、セッションレプリケーションコードで何が起こるかを正確に説明します。
TomcatA
が起動するTomcat は標準の起動シーケンスを使用して起動します。Host オブジェクトが作成されると、クラスターオブジェクトが関連付けられます。コンテキストが解析される際、web.xml ファイルに distributable 要素がある場合、Tomcat は Cluster クラス (この場合は
SimpleTcpCluster
) に、レプリケートされたコンテキスト用のマネージャーを作成するよう要求します。したがって、クラスタリングが有効で web.xml に distributable が設定されている場合、Tomcat はそのコンテキスト用にStandardManager
の代わりにDeltaManager
を作成します。クラスタークラスはメンバーシップサービス (マルチキャスト) とレプリケーションサービス (TCPユニキャスト) を起動します。アーキテクチャの詳細については、このドキュメントの後半で説明します。TomcatB
が起動するTomcatB が起動すると、TomcatA と同じシーケンスに従いますが、1つの例外があります。クラスターが起動され、メンバーシップ (TomcatA、TomcatB) が確立されます。TomcatB は、クラスター内にすでに存在するサーバー (この場合は TomcatA) からセッション状態を要求します。TomcatA はその要求に応答し、TomcatB が HTTP リクエストのリッスンを開始する前に、状態は TomcatA から TomcatB に転送されます。TomcatA が応答しない場合、TomcatB は60秒後にタイムアウトし、ログエントリを発行して起動を続行します。セッション状態は、web.xml に distributable がある各 Web アプリケーションに対して転送されます。(注: セッションレプリケーションを効率的に使用するには、すべての Tomcat インスタンスを同じように構成する必要があります。)
TomcatA
がリクエストを受け取り、セッションS1
が作成される。TomcatA に入ってくるリクエストは、セッションレプリケーションがない場合とまったく同じ方法で処理されますが、リクエストが完了すると、
ReplicationValve
がユーザーに応答が返される前にリクエストをインターセプトします。この時点で、セッションが変更されていることを検出し、TCP を使用してセッションを TomcatB にレプリケートします。シリアライズされたデータがオペレーティングシステムの TCP ロジックに渡されると、リクエストはバルブパイプラインを介してユーザーに戻ります。各リクエストに対してセッション全体がレプリケートされるため、setAttribute または removeAttribute を呼び出すことなくセッション内の属性を変更するコードもレプリケートできます。セッションがレプリケートされる回数を最適化するために、useDirtyFlag 設定パラメータを使用できます。TomcatA
がクラッシュするTomcatA がクラッシュすると、TomcatB は TomcatA がクラスターから脱落したという通知を受け取ります。TomcatB は TomcatA をメンバーシップリストから削除し、TomcatA は TomcatB で発生するいかなる変更も通知されなくなります。ロードバランサーは TomcatA から TomcatB へリクエストをリダイレクトし、すべてのセッションは最新の状態になります。
TomcatB
がセッションS1
のリクエストを受け取る特に注目すべきことはなく、TomcatB は他のリクエストと同様にリクエストを処理します。
TomcatA
が起動する起動時、TomcatA が新しいリクエストを受け付け、自身を利用可能にする前に、上記の起動シーケンス1) 2) に従います。クラスターに参加し、TomcatB にすべてのセッションの現在の状態を問い合わせます。そしてセッション状態を受信すると、ロードを完了し、HTTP/mod_jk ポートを開きます。したがって、TomcatA が TomcatB からセッション状態を受信するまで、いかなるリクエストも TomcatA に到達することはありません。
TomcatA
がリクエストを受け取り、セッション (S1
) で invalidate が呼び出されるinvalidate 呼び出しがインターセプトされ、セッションは無効化されたセッションのキューに追加されます。リクエストが完了すると、変更されたセッションを送信する代わりに、「expire」メッセージを TomcatB に送信し、TomcatB もセッションを無効化します。
TomcatB
が新しいセッション (S2
) のリクエストを受け取るステップ3) と同じシナリオ
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のクラスタリングセクションを参照してください。