22.2. JGroups を用いたクラスター通信
22.2.1. JGroups
JGroups は信頼できるメッセージングのためのツールキットで、お互いにメッセージを送信するノードを持つクラスターを作成するために使用できます。
jgroups
サブシステムは JBoss EAP で高可用性サービスのグループ通信サポートを提供します。これにより、名前付きのチャネルおよびプロトコルスタックを設定でき、チャネルのランタイム統計を表示することもできます。jgroups
サブシステムは高可用性の機能を提供する設定を使用する場合に使用できます (マネージドドメインでは ha や full-ha プロファイル、スタンドアロンサーバーは standalone-ha.xml
や standalone-full-ha.xml
設定ファイルなど)。
JBoss EAP には 2 つの JGroups スタックが事前に設定されています。
- udp
- クラスターのノードは UDP (User Datagram Protocol) マルチキャストを使用してお互いに通信します。これはデフォルトのスタックです。
- tcp
- クラスターのノードは TCP (Transmission Control Protocol) を使用してお互いに通信します。
事前設定されたスタックを使用できますが、システムの要件に合うように独自に定義をすることもできます。
TCP はエラーのチェック、パケットの順番、および輻輳制御を処理するため、TCP のオーバーヘッドは UDP よりも大きく、速度も遅くなると考えられます。JGroups は UDP のこれらの機能を処理しますが、TCP はこれらの機能を独自で処理します。信頼できないネットワークや輻輳度の高いネットワークで JGroups を使用する場合やマルチキャストが使用できない場合は、TCP を選択するとよいでしょう。
22.2.2. デフォルトの JGroups チャネルが TCP を使用するよう設定
デフォルトでは、クラスターノードは UDP プロトコルを使用して通信します。デフォルトの ee
JGroups は事前定義された udp
プロトコルスタックを使用します。
<channels default="ee"> <channel name="ee" stack="udp"/> </channels> <stacks> <stack name="udp"> <transport type="UDP" socket-binding="jgroups-udp"/> <protocol type="PING"/> ... </stack> <stack name="tcp"> <transport type="TCP" socket-binding="jgroups-tcp"/> <protocol type="MPING" socket-binding="jgroups-mping"/> ... </stack> </stacks>
一部のネットワークでは TCP のみを使用できます。以下の管理 CLI コマンドを使用して、ee
チャネルが事前設定された tcp
スタックを使用するようにします。
/subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcp)
このデフォルトの tcp
スタックは、IP マルチキャストを使用して初期クラスターメンバーシップを検出する MPING
プロトコルを使用します。他のメンバーシップ検出プロトコルに対してスタックを設定する場合は以下の項を参照してください。
22.2.3. TCPPING の設定
この手順は TCPPING
プロトコルを使用する新しい JGroups スタックを作成し、静的クラスターメンバーシップのリストを定義します。ベーススクリプトは、tcpping
スタックを作成し、この新しいスタックを使用するようデフォルトの ee
チャネルを設定します。このスクリプトの管理 CLI コマンドは環境に合わせてカスタマイズする必要があり、バッチで処理されます。
以下のスクリプトをテキストエディターにコピーし、ローカルファイルシステムに保存します。
batch # Add the tcpping stack /subsystem=jgroups/stack=tcpping:add /subsystem=jgroups/stack=tcpping/transport=TCP:add(socket-binding=jgroups-tcp) /subsystem=jgroups/stack=tcpping/protocol=TCPPING:add # Set the properties for the TCPPING protocol /subsystem=jgroups/stack=tcpping/protocol=TCPPING:write-attribute(name=properties,value={initial_hosts="HOST_A[7600],HOST_B[7600]",port_range=0,timeout=3000}) /subsystem=jgroups/stack=tcpping/protocol=MERGE3:add /subsystem=jgroups/stack=tcpping/protocol=FD_SOCK:add(socket-binding=jgroups-tcp-fd) /subsystem=jgroups/stack=tcpping/protocol=FD:add /subsystem=jgroups/stack=tcpping/protocol=VERIFY_SUSPECT:add /subsystem=jgroups/stack=tcpping/protocol=pbcast.NAKACK2:add /subsystem=jgroups/stack=tcpping/protocol=UNICAST3:add /subsystem=jgroups/stack=tcpping/protocol=pbcast.STABLE:add /subsystem=jgroups/stack=tcpping/protocol=pbcast.GMS:add /subsystem=jgroups/stack=tcpping/protocol=MFC:add /subsystem=jgroups/stack=tcpping/protocol=FRAG2:add # Set tcpping as the stack for the ee channel /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcpping) run-batch reload
定義されたプロトコルの順番が重要になることに注意してください。
環境に合わせてスクリプトを変更します。
-
マネージドドメインで実行している場合は、
/subsystem=jgroups
コマンドの前に/profile=PROFILE_NAME
を追加し、更新するプロファイルを指定する必要があります。 オプションの TCPPING プロパティーを環境に合わせて調整します。
-
initial_hosts
:HOST [ PORT ]
構文を使用した、よく知られていると考えられ、初期メンバーシップの検索に使用できるホストのコンマ区切りリスト。 -
port_range
: 必要に応じてポート範囲を割り当てることができます。ポート範囲2
を割り当て、ホストの初期ポートが7600
の場合、TCPPING はポート7600
-7602
でホストに接続しようとします。ポート範囲はinitial_hosts
で指定された各アドレスに適用されます。 -
timeout
: クラスターメンバーのタイムアウト値 (ミリ秒単位)。
-
-
マネージドドメインで実行している場合は、
スクリプトファイルを管理 CLI に渡してスクリプトを実行します。
$ EAP_HOME/bin/jboss-cli.sh --connect --file=/path/to/SCRIPT_NAME
TCPPING スタックが使用できるようになり、ネットワークの通信に TCP が使用されます。
22.2.4. TCPGOSSIP の設定
この手順は、TCPGOSSIP
プロトコルを使用する新しい JGroups スタックを作成し、外部ゴシップルーターを使用してクラスターのメンバーを検索します。ベーススクリプトは、tcpgossip
スタックを作成し、この新しいスタックを使用するようデフォルトの ee
チャネルを設定します。このスクリプトの管理 CLI コマンドは環境に合わせてカスタマイズする必要があり、バッチで処理されます。
以下のスクリプトをテキストエディターにコピーし、ローカルファイルシステムに保存します。
batch # Add the tcpgossip stack /subsystem=jgroups/stack=tcpgossip:add /subsystem=jgroups/stack=tcpgossip/transport=TCP:add(socket-binding=jgroups-tcp) /subsystem=jgroups/stack=tcpgossip/protocol=TCPGOSSIP:add # Set the properties for the TCPGOSSIP protocol /subsystem=jgroups/stack=tcpgossip/protocol=TCPGOSSIP:write-attribute(name=properties,value={initial_hosts="HOST_A[13001]"}) /subsystem=jgroups/stack=tcpgossip/protocol=MERGE3:add /subsystem=jgroups/stack=tcpgossip/protocol=FD_SOCK:add(socket-binding=jgroups-tcp-fd) /subsystem=jgroups/stack=tcpgossip/protocol=FD:add /subsystem=jgroups/stack=tcpgossip/protocol=VERIFY_SUSPECT:add /subsystem=jgroups/stack=tcpgossip/protocol=pbcast.NAKACK2:add /subsystem=jgroups/stack=tcpgossip/protocol=UNICAST3:add /subsystem=jgroups/stack=tcpgossip/protocol=pbcast.STABLE:add /subsystem=jgroups/stack=tcpgossip/protocol=pbcast.GMS:add /subsystem=jgroups/stack=tcpgossip/protocol=MFC:add /subsystem=jgroups/stack=tcpgossip/protocol=FRAG2:add # Set tcpgossip as the stack for the ee channel /subsystem=jgroups/channel=ee:write-attribute(name=stack,value=tcpgossip) run-batch reload
定義されたプロトコルの順番が重要になることに注意してください。
環境に合わせてスクリプトを変更します。
-
マネージドドメインで実行している場合は、
/subsystem=jgroups
コマンドの前に/profile=PROFILE_NAME
を追加し、更新するプロファイルを指定する必要があります。 オプションの TCPGOSSIP プロパティーを環境に合わせて調整します。
-
initial_hosts
:HOST [ PORT ]
構文を使用した、よく知られていると考えられ、初期メンバーシップの検索に使用できるホストのコンマ区切りリスト。 -
reconnect_interval
: 接続が切断されたスタブがゴシップルーターへの再接続を試みる間隔 (ミリ秒単位)。 -
sock_conn_timeout
: ソケット作成の最大時間。デフォルトは1000
ミリ秒です。 -
sock_read_timeout
: 読み取りがブロックされる最大時間 (ミリ秒単位)。0
を値として指定すると無制限にブロックされます。
-
-
マネージドドメインで実行している場合は、
スクリプトファイルを管理 CLI に渡してスクリプトを実行します。
$ EAP_HOME/bin/jboss-cli.sh --connect --file=/path/to/SCRIPT_NAME
TCPGOSSIP スタックが使用できるようになり、ネットワークの通信に TCP が使用されます。このスタックはゴシップルーターと使用するように設定されるため、JGroups メンバーは他のクラスターメンバーを見つけることができます。
22.2.5. JGroups のネットワークインターフェイスへのバインディング
デフォルトでは、JGroups は private
ネットワークインターフェイスのみへバインドし、デフォルト設定でローカルホストへ示されます。クラスタリングのトラフィックはパブリックネットワークインターフェイスで公開するべきではないため、セキュリティー上の理由で JGroups は JBoss EAP の起動中に指定された -b
引数によって定義されたネットワークインターフェイスにはバインドしません。
ネットワークインターフェイスの設定方法については ネットワークおよびポート設定 の章を参照してください。
セキュリティー上の理由で、JGroups はパブリックではないネットワークインターフェイスのみにバインドされる必要があります。また、パフォーマンス上の理由で JGroups トラフィックのネットワークインターフェイスは専用の VLAN (Virtual Local Area Network) の一部にすることが推奨されます。
22.2.6. クラスターのセキュア化
クラスターをセキュアに実行するには、複数の課題に対応する必要があります。
認証の設定
JGroups の認証は AUTH
プロトコルによって実行されます。認証されたノードのみがクラスターに参加できるようにすることが目的です。
該当のサーバー設定ファイルに AUTH
プロトコルと適切なプロパティー設定を追加します。AUTH
プロトコルは pbcast.GMS
プロトコルの直前に設定する必要があります。
<subsystem xmlns="urn:jboss:domain:jgroups:4.0"> <stacks> <stack name="udp"> <transport type="UDP" socket-binding="jgroups-udp"/> <protocol type="PING"/> <protocol type="MERGE3"/> <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/> <protocol type="FD_ALL"/> <protocol type="VERIFY_SUSPECT"/> <protocol type="pbcast.NAKACK2"/> <protocol type="UNICAST3"/> <protocol type="pbcast.STABLE"/> <protocol type="AUTH"> <property name="auth_class">org.jgroups.auth.MD5Token</property> <property name="auth_value">mytoken</property> <!-- Change this password --> <property name="token_hash">MD5</property> </protocol> <protocol type="pbcast.GMS"/> <protocol type="UFC"/> <protocol type="MFC"/> <protocol type="FRAG2"/> </stack> </stacks> </subsystem>
暗号化の設定
JGroups はクラスターのメンバーが共有する秘密鍵を使用してメッセージを暗号化します。送信元は共有する秘密鍵を使用してメッセージを暗号化し、受信先は同じ秘密鍵を使用してメッセージを復号化します。対称暗号化 は SYM_ENCRYPT
プロトコルを使用して設定され、ノードは共有のキーストアを使用して秘密鍵を取得します。非対称暗号化 は ASYM_ENCRYPT
プロトコルを使用して設定され、ノードは AUTH
を使用して認証された後にクラスターのコーディネーターから秘密鍵を取得します。
SYM_ENCRYPT
および ASYM_ENCRYPT
プロトコルにアクセスするには、Red Hat JBoss Enterprise Application Platform 7.0 更新 01 以降の累積パッチを JBoss EAP インストールに適用する必要があります。
累積パッチの適用については、JBoss EAP パッチ適用およびアップグレードガイドを 参照してください。
対称暗号化の使用
SYM_ENCRYPT
を使用するには、各ノードの JGroups 設定で参照されるキーストアを設定する必要があります。
キーストアを作成します。
以下のコマンドでは、
を適切な JGroups JAR バージョンに置き換え、PASSWORD をキーストアパスワードに置き換えます。VERSION
$ java -cp EAP_HOME/modules/system/layers/base/org/jgroups/main/jgroups-VERSION.jar org.jgroups.demos.KeyStoreGenerator --alg AES --size 128 --storeName defaultStore.keystore --storepass PASSWORD --alias mykey
これにより、JGroups 設定で参照される
defaultStore.keystore
ファイルが生成されます。jgroups
サブシステムでSYM_ENCRYPT
プロトコルを設定します。該当するサーバー設定ファイルに、
SYM_ENCRYPT
プロトコルと適切なプロパティー設定を追加します。SYM_ENCRYPT
プロトコルはpbcast.NAKACK2
の直前に設定する必要があります。<subsystem xmlns="urn:jboss:domain:jgroups:4.0"> <stacks> <stack name="udp"> <transport type="UDP" socket-binding="jgroups-udp"/> <protocol type="PING"/> <protocol type="MERGE3"/> <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/> <protocol type="FD_ALL"/> <protocol type="VERIFY_SUSPECT"/> <protocol type="SYM_ENCRYPT"> <property name="provider">SunJCE</property> <property name="sym_algorithm">AES</property> <property name="encrypt_entire_message">true</property> <property name="keystore_name">/path/to/defaultStore.keystore</property> <property name="store_password">PASSWORD</property> <property name="alias">mykey</property> </protocol> <protocol type="pbcast.NAKACK2"/> <protocol type="UNICAST3"/> <protocol type="pbcast.STABLE"/> <protocol type="pbcast.GMS"/> <protocol type="UFC"/> <protocol type="MFC"/> <protocol type="FRAG2"/> </stack> </stacks> </subsystem>
SYM_ENCRYPT
を使用する場合、AUTH
の設定は任意です。
非対称暗号化の使用
jgroups
サブシステムでASYM_ENCRYPT
プロトコルを設定します。該当のサーバー設定ファイルに
ASYM_ENCRYPT
プロトコルと適切なプロパティー設定を追加します。SYM_ENCRYPT プロトコルはpbcast.NAKACK2
の直前に設定する必要があります。<subsystem xmlns="urn:jboss:domain:jgroups:4.0"> <stacks> <stack name="udp"> <transport type="UDP" socket-binding="jgroups-udp"/> <protocol type="PING"/> <protocol type="MERGE3"/> <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/> <protocol type="FD_ALL"/> <protocol type="VERIFY_SUSPECT"/> <protocol type="ASYM_ENCRYPT"> <property name="encrypt_entire_message">true</property> <property name="sym_keylength">128</property> <property name="sym_algorithm">AES/ECB/PKCS5Padding</property> <property name="asym_keylength">512</property> <property name="asym_algorithm">RSA</property> </protocol> <protocol type="pbcast.NAKACK2"/> <protocol type="UNICAST3"/> <protocol type="pbcast.STABLE"/> <!-- Configure AUTH protocol here --> <protocol type="pbcast.GMS"/> <protocol type="UFC"/> <protocol type="MFC"/> <protocol type="FRAG2"/> </stack> </stacks> </subsystem>
jgroups
サブシステムでAUTH
プロトコルを設定します。ASYM_ENCRYPT
にはAUTH
が必要です。手順については、認証の設定 セクションを参照してください。
22.2.7. JGroups スレッドプールの設定
jgroups
サブシステムには default
、internal
、oob
、および timer
スレッドプールが含まれます。これらのプールはすべての JGroups スタックに設定できます。
以下の表は、各スレッドプールに設定できる属性とデフォルト値を表しています。
スレッドプール名 | keepalive-time | max-threads | min-threads | queue-length |
---|---|---|---|---|
default | 60000L | 300 | 20 | 100 |
internal | 60000L | 4 | 2 | 100 |
oob | 60000L | 300 | 20 | 0 |
timer | 5000L | 4 | 2 | 500 |
以下の構文を使用して、管理 CLI で JGroups スレッドプールを設定します。
/subsystem=jgroups/stack=STACK_TYPE/transport=TRANSPORT_TYPE/thread-pool=THREAD_POOL_NAME:write-attribute(name=ATTRIBUTE_NAME, value=ATTRIBUTE_VALUE)
以下は、 udp
スタックの default
スレッドプールで max-threads
の値を 500
に設定する管理 CLI コマンドの例になります。
/subsystem=jgroups/stack=udp/transport=UDP/thread-pool=default:write-attribute(name="max-threads", value="500")
22.2.8. JGroups の送受信バッファーの設定
バッファーサイズ警告の解決
デフォルトでは、JGroups は特定の送信バッファー値と受信バッファー値を使用して設定されます。オペレーティングシステムが利用可能なバッファーサイズを制限し、JBoss EAP が設定済みのバッファーサイズを使用できないことがあります。このような場合、以下と似た警告が JBoss EAP のログに記録されます。
WARNING [org.jgroups.protocols.UDP] (ServerService Thread Pool -- 68) JGRP000015: the send buffer of socket DatagramSocket was set to 640KB, but the OS only allocated 212.99KB. This might lead to performance problems. Please set your max send buffer in the OS correctly (e.g. net.core.wmem_max on Linux) WARNING [org.jgroups.protocols.UDP] (ServerService Thread Pool -- 68) JGRP000015: the receive buffer of socket DatagramSocket was set to 20MB, but the OS only allocated 212.99KB. This might lead to performance problems. Please set your max receive buffer in the OS correctly (e.g. net.core.rmem_max on Linux)
これに対応するには、オペレーティングシステムのマニュアルでバッファーサイズを増やす方法を参照してください。Red Hat Enterprise Linux システムの場合は、root ユーザーとして /etc/sysctl.conf
を編集し、システムの再起動後も維持されるバッファーサイズの最大値を設定します。以下に例を示します。
# Allow a 25MB UDP receive buffer for JGroups net.core.rmem_max = 26214400 # Allow a 1MB UDP send buffer for JGroups net.core.wmem_max = 1048576
/etc/sysctl.conf
を編集後、sysctl -p
を実行して変更を反映します。
JGroups バッファーサイズの設定
以下のトランスポートプロパティーを UDP および TCP JGroups スタックに設定すると、JBoss EAP が使用する JGroups バッファーサイズを設定できます。
- UDP スタック
-
ucast_recv_buf_size
-
ucast_send_buf_size
-
mcast_recv_buf_size
-
mcast_send_buf_size
-
- TCP スタック
-
recv_buf_size
-
send_buf_size
-
JGroups バッファーサイズは、管理コンソールまたは管理 CLI を使用して設定できます。
以下の構文を使用して、管理 CLI で JGroups バッファーサイズプロパティーを設定します。
/subsystem=jgroups/stack=STACK_NAME/transport=TRANSPORT/property=PROPERTY_NAME:add(value=BUFFER_SIZE)
以下は、tcp
スタックで recv_buf_size
プロパティーを 20000000
に設定する管理 CLI コマンドの例になります。
/subsystem=jgroups/stack=tcp/transport=TRANSPORT/property=recv_buf_size:add(value=20000000)
JGroups バッファーサイズは、管理コンソールを使用して設定することもできます。設定 タブから JGroups サブシステムに移動し、関連するスタックを表示して、トランスポート を選択し、トランスポートの プロパティー タブを選択します。
22.2.9. JGroups トラブルシューティング
22.2.9.1. ノードがクラスターを形成しない
マシンで IP マルチキャストが正しくセットアップされていることを確認します。JBoss EAP には、IP マルチキャストのテストに使用できる McastReceiverTest
と McastSenderTest
の 2 つのテストプログラムが含まれています。
ターミナルで McastReceiverTest
を開始します。
$ java -cp EAP_HOME/bin/client/jboss-client.jar org.jgroups.tests.McastReceiverTest -mcast_addr 230.11.11.11 -port 5555
別のターミナルウインドウで McastSenderTest
を開始します。
$ java -cp EAP_HOME/bin/client/jboss-client.jar org.jgroups.tests.McastSenderTest -mcast_addr 230.11.11.11 -port 5555
特定のネットワークインターフェイスカード (NIC) をバインドする場合は、-bind_addr
を使用します。YOUR_BIND_ADDRESS はバインドする NIC の IP アドレスに置き換えます。送信側と受信側の両方にこのパラメーターを使用します。
YOUR_BIND_ADDRESS
McastSenderTest
ターミナルウインドウで入力すると McastReceiverTest
ウインドウに出力が表示されます。表示されない場合は以下の手順に従います。
-
送信側のコマンドに
-ttl VALUE
を追加して、マルチキャストパケットの TTL (time-to-live) を増やします。このテストプログラムによって使用されるデフォルトの値は 32 で、
はVALUE
255
以下である必要があります。 - マシンに複数のインターフェイスがある場合は、適切なインターフェイスを使用していることを確認します。
- システム管理者に連絡し、マルチキャストが選択したインターフェイスで動作することを確認します。
クラスターの各マシンでマルチキャストが適切に動作したら、送信側と受信側を別々のマシンに配置し、テストを繰り返します。
22.2.9.2. 障害検出での不明なハートビートの原因
ハートビートの確認が一定時間 (T
) 受信されないと、障害検出 (FD) によってクラスターメンバーが原因として疑われることがあります。T は timeout
および max_tries
によって定義されます。
たとえば、ノード A、B、C、および D のクラスターがあり、A が B、B が C、C が D、D が A を ping する場合、以下のいずれかの理由で C が疑われます。
-
B または C が CPU の使用率が 100% の状態で
T
秒よりも長く稼働している場合。この場合、 C がハートビート確認を B に送信しても CPU の使用率が 100% であるため B が確認を処理できないことがあります。 - B または C がガベッジコレクションを実行している場合、上記と同じ結果になります。
- 上記 2 件の組み合わせ。
- ネットワークによるパケットの損失が発生する場合。通常、ネットワークに大量のトラフィックがあり、スイッチがパケットを破棄すると発生します (通常は最初にブロードキャスト、次に IP マルチキャスト、そして最後に TCP パケットが破棄されます)。
-
B または C がコールバックを処理する場合。C が処理に
T
+ 1 秒かかるリモートメソッド呼び出しをチャネル上で受信した場合、C はハートビートを含む他のメッセージを処理できません。そのため、B はハートビート確認を受信せず、C が疑われます。