第27章 JGroups サービス
JGroups は JBoss Enterprise Application Platform クラスターに対する基礎のグループ通信サポートを提供します。 クラスター化されたサービスと Groups との対話については、 「JGroups とのグループ通信」 に説明されています。 本章では、 この対話の詳細に重点を置き、設定の詳細やトラブルシューティングのヒントを中心に説明します。
本章は完全な JGroups ドキュメントではありません。 JGroups に関する詳細を知りたい場合は、 以下を参照してください。
- http://jgroups.org/ug.html の JGroups プロジェクトドキュメント。
- https://www.jboss.org/community/wiki/JGroups に掲載されている jboss.org の JGroups wiki ページ。
本章の最初の項では、 多くの JGroups 設定オプションの詳細を取り上げます。 JBoss Enterprise Application Platform にはデフォルトの JGroups 設定のセットが同梱されています。 ほとんどのアプリケーションはデフォルト設定でそのまま動作します。 ネットワーク要件やパフォーマンス要件が特別なアプリケーションをデプロイする場合のみ設定を変更する必要があります。
27.1. JGroups チャネルのプロトコルスタックを設定
JGroups のフレームワークは、 クラスターでノード間のピアツーピア通信を可能にするサービスを提供します。 通信は通信チャンネル上で発生します。 チャネルはネットワーク通信プロトコルのスタックより構築され、 各チャネルはチャネル全体の動作に特定機能を追加します。 プロトコルによって提供される主な機能には、 トランスポート、 クラスターディスカバリ、 メッセージの順序付け、 無損失メッセージ配信、 失敗したピアの検知、 クラスターメンバーシップの管理サービスなどが含まれます。
図27.1「JGroups 内のプロトコルスタック」 は、 各メンバのチャネルが JGroups プロトコルのスタックで構成される概念的クラスターです。

図27.1 JGroups 内のプロトコルスタック
本項では、 チャネルへ追加する動作タイプにより 、最も頻繁に使用されるプロトコルについて取り上げます。 各プロトコルによって公開される主な設定属性についても説明しますが、 これらの属性は熟練ユーザーのみが変更すべきであるため、 プロトコルの目的を理解することに重点を置きます。
JBoss Enterprise Application Platform で使用される JGroups 設定は、
$JBOSS_HOME/server/production/deploy/cluster/jgroups-channelfactory.sar/META-INF/jgroups-channelfactory-stacks.xml ファイル内でネストされた要素として表示されます。このファイルは ChannelFactory サービスによって構文分析され、このコンテンツを使用して、正しく設定されたチャネルを必要とするクラスター化サービスへ提供します。ChannelFactory サービスの詳細は、「チャネルファクトリサービス」 を参照してください。
以下は、
jgroups-channelfactory-stacks.xml のプロトコルスタック設定例になります。
<stack name="udp-async"
description="Same as the default 'udp' stack above, except message bundling
is enabled in the transport protocol (enable_bundling=true).
Useful for services that make high-volume asynchronous
RPCs (e.g. high volume JBoss Cache instances configured
for REPL_ASYNC) where message bundling may improve performance.">
<config>
<UDP
singleton_name="udp-async"
mcast_port="${jboss.jgroups.udp_async.mcast_port:45689}"
mcast_addr="${jboss.partition.udpGroup:228.11.11.11}"
tos="8"
ucast_recv_buf_size="20000000"
ucast_send_buf_size="640000"
mcast_recv_buf_size="25000000"
mcast_send_buf_size="640000"
loopback="true"
discard_incompatible_packets="true"
enable_bundling="true"
max_bundle_size="64000"
max_bundle_timeout="30"
ip_ttl="${jgroups.udp.ip_ttl:2}"
thread_naming_pattern="cl"
timer.num_threads="12"
enable_diagnostics="${jboss.jgroups.enable_diagnostics:true}"
diagnostics_addr="${jboss.jgroups.diagnostics_addr:224.0.0.75}"
diagnostics_port="${jboss.jgroups.diagnostics_port:7500}"
thread_pool.enabled="true"
thread_pool.min_threads="8"
thread_pool.max_threads="200"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="true"
thread_pool.queue_max_size="1000"
thread_pool.rejection_policy="discard"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="8"
oob_thread_pool.max_threads="200"
oob_thread_pool.keep_alive_time="1000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.rejection_policy="discard"/>
<PING timeout="2000" num_initial_members="3"/>
<MERGE2 max_interval="100000" min_interval="20000"/>
<FD_SOCK/>
<FD timeout="6000" max_tries="5" shun="true"/>
<VERIFY_SUSPECT timeout="1500"/>
<BARRIER/>
<pbcast.NAKACK use_mcast_xmit="true" gc_lag="0"
retransmit_timeout="300,600,1200,2400,4800"
discard_delivered_msgs="true"/>
<UNICAST timeout="300,600,1200,2400,3600"/>
<pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
max_bytes="400000"/>
<VIEW_SYNC avg_send_interval="10000"/>
<pbcast.GMS print_local_addr="true" join_timeout="3000"
shun="true"
view_bundling="true"
view_ack_collection_timeout="5000"
resume_task_timeout="7500"/>
<FC max_credits="2000000" min_threshold="0.10"
ignore_synchronous_response="true"/>
<FRAG2 frag_size="60000"/>
<!-- pbcast.STREAMING_STATE_TRANSFER/ -->
<pbcast.STATE_TRANSFER/>
<pbcast.FLUSH timeout="0" start_flush_timeout="10000"/>
</config>
</stack><config> 要素にはすべての JGroups 設定データが含まれます。 この情報は、 概念的にソケットと似ている JGroups チャネルの設定に使用され、 クラスターのピア間の通信を管理します。 <config> 要素内部の各要素は特定の JGroups プロトコルを定義します。 各プロトコルは 1 つの機能を実行し、 これらの機能の組み合わせによってチャネル全体の特性が定義されます。 今後の項では、一般的に使用されるプロトコルやオプションについて説明し、 各プロトコルに使用できるオプションについて取り上げます。
27.1.1. 一般的な設定プロパティ
次のプロパティが以下で説明するすべての JGroups プロトコルにによって公開されます。
statsは、 AS の JMX コンソールや JGroups Probe ユーティリティなどのツールによって公開される操作に対するランタイム統計をプロトコルが収集するかを判断します。 収集される統計はプロトコルによって異なります。 デフォルトはtrueになります。
注記
JBoss Application Server 3.x および 4.x で使用された JGroups バージョンのすべてのプロトコルは
down_thread 属性と up_thread 属性を公開しました。 JBoss Application Server 5 とそれ以降のバージョンに含まれる JGroups のバージョンはこれら属性を使用しません。 また、 これらの属性がプロトコルに対して設定されると、 WARN メッセージがサーバーログに書き込まれます。
27.1.2. トランスポートプロトコル
トランスポートプロトコルは、 メッセージをネットワークに送信、あるいはメッセージをネットワークから受信します。 また、 トランスポートプロトコルは使用されるスレッドプールを管理し、 受信メッセージをプロトコルスタックのより高いアドレスに送信します。 JGroups はトランスポートプロトコルとして
UDP、 TCP、 TUNNEL をサポートします。
注記
UDP、 TCP、 TUNNEL プロトコルは相互に排他的です。 各 JGroups Config エレメントには 1 つのトランスポートプロトコルのみを指定できます。
27.1.2.1. UDP 設定
UDP は JGroups の推奨プロトコルです。 UDP はマルチキャスト (または特別な設定の場合は複数のユニキャスト) を使用してメッセージの送受信を行います。 クラスターサービスのトランスポートプロトコルに UDP を選択する場合は、 JGroups
config 要素内の UDP サブ要素に設定する必要があります。 例は次の通りです。
<UDP
singleton_name="udp-async"
mcast_port="${jboss.jgroups.udp_async.mcast_port:45689}"
mcast_addr="${jboss.partition.udpGroup:228.11.11.11}"
tos="8"
ucast_recv_buf_size="20000000"
ucast_send_buf_size="640000"
mcast_recv_buf_size="25000000"
mcast_send_buf_size="640000"
loopback="true"
discard_incompatible_packets="true"
enable_bundling="true"
max_bundle_size="64000"
max_bundle_timeout="30"
ip_ttl="${jgroups.udp.ip_ttl:2}"
thread_naming_pattern="cl"
timer.num_threads="12"
enable_diagnostics="${jboss.jgroups.enable_diagnostics:true}"
diagnostics_addr="${jboss.jgroups.diagnostics_addr:224.0.0.75}"
diagnostics_port="${jboss.jgroups.diagnostics_port:7500}"
thread_pool.enabled="true"
thread_pool.min_threads="8"
thread_pool.max_threads="200"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="true"
thread_pool.queue_max_size="1000"
thread_pool.rejection_policy="discard"
oob_thread_pool.enabled="true"
oob_thread_pool.min_threads="8"
oob_thread_pool.max_threads="200"
oob_thread_pool.keep_alive_time="1000"
oob_thread_pool.queue_enabled="false"
oob_thread_pool.rejection_policy="discard"/>
JGroups のトランスポート設定には、 複数の属性を使用できます。 最初に、
UDP プロトコルに使用できる属性を取り上げた後、 TCP プロトコルや TUNNEL プロトコルが使用する属性について説明します。
UDP プロトコル特有の属性は次の通りです。
- ip_mcast は IP マルチキャスト機能を使用するかどうかを指定します。 デフォルト値は
trueです。falseに設定された場合は、 1 つのマルチキャストパケットではなく複数のユニキャストパケットが送信されます。UDPプロトコルより送信されるすパケットはすべて UDP データグラムです。 - mcast_addr はグループ (クラスターなど) との通信に対するマルチキャストアドレス (クラス D) を指定します。 JBoss AS の標準的なプロトコルスタック設定は、 システムプロパティ
jboss.partition.udpGroupの値 (設定されている場合) をこの属性に使用します。 JBoss Application Server の起動時に-uコマンドラインスイッチを使用すると、 この値を設定します。 この設定属性を使用して JGroups チャネルを適切に別のチャネルより分離する方法については、 「JGroups チャネルの分離」 を参照してください。 この属性を省略すると、 デフォルト値は228.11.11.11になります。 - mcast_port はグループとマルチキャスト通信するポートを指定します。 この設定属性を使用して JGroups チャネルを適切に別のチャネルより分離する方法については、 「JGroups チャネルの分離」 を参照してください。 この属性を省略すると、 デフォルト値は
45688になります。 mcast_send_buf_size、mcast_recv_buf_size、ucast_send_buf_size、ucast_recv_buf_sizeは、 JGroups がオペレーティングシステムより要求するソケットの送受信バッファーサイズを指定します。 バッファーサイズを大きくすると、 バッファーのオーバーフローによるパケット落ちを防ぐことができます。 しかし、 ソケットバッファーサイズはオペレーティングシステムレベルで制限されるため、 希望のバッファーサイズを得るにはオペレーティングシステムレベルでの設定が必要となることがあります。 詳細は 「OS UDP の バッファー制限を設定してUDPのパフォーマンスを改善」 を参照してください。- bind_port はユニキャスト受信ソケットがバインドされるポートを指定します。 デフォルトは
0で、 短命ポートを使用します。 - port_range は、
bind_portによって特定されたポートがない場合に試行するポート数を指定します。 デフォルトは1で、bind_portのみが試行されます。 - ip_ttl は、IP マルチキャストパケットの TTL (生存期間) を指定します。TTL は、マルチキャストネットワーキングで一般的に使用される用語ですが、この値はネットワーキング装置がパケットを破棄するまでパケットがネットワークを通過する回数を表すためこの用語は実際には適切ではありません。
- tos はユニキャストおよびマルチキャストデータグラムを送信するトラフィッククラスを指定します。
すべてのトランスポートプロトコルで共通しているため、
TCP や TUNNEL で同じ意味を持つ属性は次の通りです。
- singleton_name はトランスポートプロトコル設定に固有の名前を提供します。 アプリケーションサーバーの
ChannelFactoryによって使用され、 同じトランスポートプロトコルを使用する異なるチャネルによるトランスポートプロトコルインスタンスの共有をサポートします。 「JGroups 共有トランスポート」を参照してください。 - bind_addr はメッセージの送受信を行うインターフェースを指定します。 デフォルトでは、 JGroups はシステムプロパティ
jgroups.bind_addrの値を使用します。-bコマンドラインスイッチを使用して設定することもできます。 JGroups ソケットのバインドに関する詳細は、 「その他設定の問題」 を参照してください。 - receive_on_all_interfaces はこのノードがすべてのインターフェースでマルチキャストをリッスンするかを指定します。 デフォルト値は
falseです。 マルチキャストの受信についてはbind_addrプロパティよりも優先されます。 ただし、 マルチキャストの送信には引き続きbind_addr(設定されている場合) が使用されます。 - send_on_all_interfaces は、 マシンに複数のネットワークインターフェースコントローラがある場合に、 このノードがすべてのネットワークインターフェースコントローラから UDP パケットを送信するかどうかを指定します。 同じマルチキャストメッセージが N 回送信されることを意味するため、 注意して使用してください。
- receive_interfaces は、マルチキャストを受信するインターフェースの一覧を指定します。マルチキャスト受信ソケットはこれらのインターフェースすべてでリッスンします。IP アドレスまたはインターフェース名をカンマで区切ったリストになります (例:
192.168.5.1,eth1,127.0.0.1)。 - send_interfacesは、マルチキャストを送信するインターフェースの一覧を指定します。マルチキャスト送信ソケットはこれらのインターフェースすべてでリッスンします。 IP アドレスまたはインターフェース名をカンマで区切ったリストになります (例:
192.168.5.1,eth1,127.0.0.1)。 そのため、同じマルチキャストメッセージが N 回送信されるため、注意して使用してください。 - enable_bundling は、メッセージのバンドルを有効にするかを指定します。
trueの場合、max_bundle_sizeバイトが累積されるかmax_bundle_timeミリ秒が経過するまで (いずれか早く発生する期間) トランスポートプロトコルが送信メッセージをキューに入れます。 次にキューに入ったメッセージを 1 つの大きなメッセージにまとめてから送信します。 このメッセージは受信側で元に戻されます。 デフォルト値はfalseです。メッセージのバンドルは、 送信元が受信先からの応答待機をブロックしない場合 (REPL_ASYNCに対して設定された JBoss Cache インスタンスなど)、 大量のメッセージ送信に使用されるチャネルに対してパフォーマンスの大幅な改善を期待できます。 送信元が応答待機をブロックする必要がある場合、 アプリケーションの待ち時間が大幅に長くなるため、 JBoss Cache インスタンスがREPL_SYNCに設定された場合など、 特定の場合でのみ推奨されます。 - loopback は、 グループにメッセージを送信するスレッド自体が、 配信のためメッセージをスタックに戻すかを指定します (グループに送信されるメッセージは常に送信するノードにも配信されます)。
falseの場合、 送信するスレッドはメッセージを持ちません。 トランスポートプロトコルがネットワークからメッセージを読み取るために待機し、 配信にメッセージ配信プールスレッドの 1 つを使用します。 デフォルトはfalseですが、 ネットワークインターフェースが停止した時にチャネルがメッセージを受信できるようにするためtrueが推奨されます。 - discard_incompatibe_packets は、 別バージョンの JGroups を使用するピアから送信されたパケットを破棄するか指定します。 クラスター内の各メッセージには JGroups バージョンのタグが付けられます。
discard_incompatible_packetsがtrueに設置されると、 別バージョンの JGroups からの受信されたメッセージは静かに破棄されます。 これ以外の場合は警告がログに記録されます。 メッセージは配信されません。 デフォルト値はfalseです。 - enable_diagnostics は、 アドレス
diagnostics_addrとポートdiagnostics_port上でマルチキャストソケットを開け、 JGroup の Probe ユーティリティが送信した分析要求をリッスンするかを指定します。 - 通常の受信メッセージをスタックに運ぶため JGroups が使用するスレッドプールの動作は、 様々な thread_pool 属性が設定します。 これらの属性は、
java.util.concurrent.ThreadPoolExecutorServiceのインスタンスに対してコンストラクターの引数を提供します。 上記の例では、 プールの最低またはコアサイズが 8 スレッドで、 最大サイズは 200 になります。 9 つ以上のプールスレッドが作成されると、 メッセージの伝達より返されたスレッドは、 伝達する新しいメッセージが割り当てられるまで最大 5000 ミリ秒待機し、 その後終了します。 メッセージを伝達するスレッドがない場合、 ソケット外でメッセージを読み取る個別のスレッドがメッセージをキューに入れます。 キューは最大 1000 メッセージを保持することができます。 キューがいっぱいの場合、ソケット外でメッセージを読み取るスレッドはメッセージを破棄します。 - 受信メッセージをプロトコルスタックへ運ぶために使用される
java.util.concurrent.ThreadPoolExecutorServiceを設定するという面で、 oob_thread_pool 属性は thread_pool 属性と似ています。この場合、 OOB (帯域外、Out Of Band) メッセージと呼ばれる特別なタイプのメッセージを運ぶためにプールが使用されます。 OOB メッセージは、 NAKACK や UNICAST などのプロトコルの順番配信要件を免除されるため、 NAKACK や UNICAST が特定送信元のメッセージをキューに入れている場合でも、 OOB メッセージはスタックへ配信されます。 OOB メッセージは JGroups プロトコルによって頻繁に内部で使用され、 アプリケーションによって使用されることもあります。 例えば、 JBoss Cache がREPL_SYNCモードである場合、 2 フェーズコミットプロトコルの第 2 フェーズ にOOB メッセージを使用します。
27.1.2.2. TCP 設定
JGroups ベースのクラスターは TCP 接続でも動作します。 クラスターサイズが大きくなると、 TCP は UDP より多くのネットワークトラフィックを生成します。 TCP は基本的にはユニキャストのプロトコルです。 マルチキャストメッセージを送信するために、 JGroups は複数の TCP ユニキャストを使用します。 TCP をトランスポートプロトコルとして使用するには、 JGroups
config 要素内の TCP 要素を定義してください。 TCP 要素の例は次の通りです。
<TCP singleton_name="tcp"
start_port="7800" end_port="7800"/>
TCP 要素固有の属性は次の通りです。
start_portとend_portは、 サーバーがバインドする TCP ポートの範囲を定義します。 サーバーソケットは、start_port以降の最初に利用できるポートへバインドされます。end_portの前に利用可能なポートが見つからない場合 (他のソケットによってポートが使用されている場合など)、 サーバーは例外をスローします。end_portの指定がない場合や、end_portがstart_portよりも低い場合、 ポートの範囲に上限が適用されません。start_portとend_portが同じ場合、 指定されたポートが使用できないとstart_portが失敗するため、 JGroups は指定されたポートの使用を強制されます。 デフォルト値は7800です。0を設定すると、 オペレーティングシステムがポートを選択します (TCCPINGにノードと必要ポートをリストする必要があるため、MPINGやTCPGOSSIPのディスカバリプロトコルを使用する場合にのみ動作します)。- TCP の bind_port は
start_portのエイリアスとして動作します。 内部に設定されるとstart_portを設定します。 - recv_buf_size, send_buf_size は受信と送信のバッファーサイズを定義します。 バッファーのオーバーフローでパケットが破棄される可能性を低減するため、 受信バッファーサイズは大きめにした方がよいでしょう。
- conn_expire_time はトラフィックが受信されていない場合、 ここに指定した時間 (ミリ秒単位) を経過すると reaper によって接続を閉じることができます。
- reaper_interval は reaper を実行する間隔を指定します (ミリ秒単位)。 いずれの値も 0 の場合、 reap は行われません。 いずれかの値が > 0 になる場合、 reap が有効になります。デフォルトでは、reaper_interval が 0 です (つまり、reaper を実行しません)。
- sock_conn_timeout は、ソケット作成に関する最大時間をミリ秒単位で指定します。初めて検索を実行し、ピアがハングする場合は、いつまでも待たずにタイムアウト後に他のメンバに対して ping を実行します。これにより、メンバーがまったく見つからない可能性が少なくなります。デフォルト値は 2000 です。
- use_send_queues は各接続に別の送信キューを使用するかどうかを指定します。これにより、ピアがハングしたときに書き込みブロックが回避されます。デフォルト値は true です。
- external_addr は、他のグループメンバにブロードキャストする外部 IP アドレス (ローカルアドレスと異なる場合) を指定します。これは、NAT (Network Address Translation) とファイアウォールの背後にあるプライベートネットワーク上のノード を使用し、そのノードに外部から見えるアドレス (バインドされるローカルアドレスとは異なります) のみを使用してルーティングできる場合に役に立ちます。したがって、ノードは、引き続きローカルアドレスにバインドできる一方で外部アドレスをブロードキャストするよう設定できます。これにより、ファイアウォール外部のノードはファイアウォール内部のノード (ただし、外部アドレスのもののみ) に引き続きルーティングできるため、TUNNEL プロトコル (つまり、中央ゴシップルーターの要件) を使用する必要がなくなります。external_addr を設定しない場合、ファイアウォール背後のノードはプライベートアドレスをそのアドレスにルーティングできない他のノードにブロードキャストします。
- skip_suspected_members は、ユニキャストメッセージを該当すると思われるメンバに送信するかどうかを指定します。デフォルト値は true です。
- tcp_nodelay は TCP_NODELAY を指定します。デフォルトでは TCP はメッセージに nagle を使用します。つまり、概念的に複数の小さいメッセージは大きいメッセージにまとめられます。同期クラスターメソッド呼び出しを行う場合は、メッセージバンドルを無効にするのに加えて nagle を無効にする必要があります (
enable_bundlingを false に設定します)。nagle を無効にするには、tcp_nodelayを true に設定します。デフォルト値は false です。
注記
UDP プロトコルの項で説明したすべてのプロトコルに共通する属性も TCP に適用されます。
27.1.2.3. TUNNEL の設定
TUNNEL プロトコルはメッセージの送信を処理するため外部ルーターを使用します。 外部ルーターは org.jgroups.stack.GossipRouter メインクラスを実行する Java プロセスです。 各ノードはこのルーターに登録する必要があります。 すべてのメッセージがこのルーターに送信されてからその目的地に転送されます。 TUNNEL の方法はファイアウォールの背後にあるノードとの通信を設定するために使用できます。 ノードはファイアウォールを通過して GossipRouter への TCP 接続を確立することができます (80番ポートの使用可)。 ファイアウォールの多くは、 ファイアウォール内部のホストへの TCP 接続を外部ホストが開始するすることを許可しないため、 ルーターによるファイアウォール背後のノードへのメッセージ送信にもこの接続が使用されます。 TUNNEL 設定は、 次のように JGroups <config> 要素内の TUNNEL 要素で定義されます。
<TUNNEL singleton_name="tunnel"
router_port="12001"
router_host="192.168.5.1"/>
TUNNEL 要素内で使用できる属性は以下の通りです。
- router_host は GossipRouter が稼働しているホストを指定します。
- router_port は GossipRouter がリッスンしているポートを指定します。
- reconnect_interval は、 接続が確立できない場合に
TUNNELがGossipRouterへの接続を試行する間隔 (ミリ秒単位) を指定します。 デフォルトは5000です。
注記
UDP プロトコルの項で説明したすべてのプロトコルに共通する属性も
TUNNEL に適用されます。
27.1.3. ディスカバリプロトコル
ノード上のチャネルが最初に接続すると、 互換性のあるチャネルを実行する他のノードやコーディネータ (新しいノードをグループへ参加させるノード) として機能しているノードを判断する必要があります。 ディスカバリプロトコルは、 クラスターのアクティブなノードを検索し、 どのノードがコーディネータであるか判断するために使用されます。そして、コーディネータの GMS と通信し、 新たに接続したノードをグループに追加するグループメンバーシッププロトコル (GMS) にその情報が提供されます (グループメンバーシッププロトコルについての詳細は「グループメンバーシップ (GMS)」 を参照してください)。
ディスカバリプロトコルは、 クラスターのスプリットを検知するために結合プロトコル (「マージ (MERGE2)」 参照) も支援します。
ディスカバリプロトコルはトランスポートプロトコルの上に位置しているため、 使用するトランスポートプロトコルに応じて異なるディスカバリプロトコルの使用を選択することができます。 また、 JGroups
<config> エレメント内のサブ要素として設定することもできます。
27.1.3.1. PING
PING は PING 要求を IP マルチキャストアドレスにマルチキャストするか、ゴシップルーターに接続することによって動作する検索プロトコルです。したがって、PING は通常、UDP または TUNNEL トランスポートプロトコルの上部に位置します。各ノードはパケット {C, A} で応答します。ここで、C はコーディネータのアドレス、A は自身のアドレスを示します。ミリ秒単位のタイムアウトの経過後または num_initial_members の応答後、参加するノードは応答からコーディネータを調べ、JOIN 要求をコーディネータに送信します。誰も応答しない場合は、グループの最初のメンバと見なされます。
以下は IP マルチキャスト用の PING 設定の例です。
<PING timeout="2000"
num_initial_members="3"/>
以下は Gossip Router に接続するための PING 設定の別の例です。
<PING gossip_host="localhost"
gossip_port="1234"
timeout="2000"
num_initial_members="3"/>PING 要素内で使用できる属性は以下の通りです。
- timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
- num_initial_members は、待機する最大応答数を指定します (タイムアウトが経過していない場合)。デフォルト値は 2 です。
- gossip_host GossipRouter が稼働しているホストを指定します。
- gossip_port GossipRouter がリッスンしているポートを指定します。
- gossip_refresh は GossipRouter からのリースの間隔を指定します (ミリ秒単位)。デフォルト値は 20000 です。
- initial_hosts は、 ディスカバリで ping されるアドレスやポートをコンマで区切った一覧です (例:
host1[12345],host2[23456])。 デフォルトはnullで、 マルチキャストディスカバリが使用されます。initial_hostsを指定した場合、 ウェルノウンホストの一部だけでなく可能なクラスターメンバーすべてをリストに含める必要があります。 すべてをリストしないと、MERGE2クラスタースプリットディスカバリが確実に動作しません。
gossip_host と gossip_port の両方が定義されると、 クラスターは初期のディスカバリに GossipRouter を使用します。 initial_hosts が指定されると、 クラスターはディスカバリにその静的アドレス一覧を ping します。 これ以外は、 クラスターはディスカバリに IP マルチキャスティングを使用します。
注記
ディスカバリフェーズが返されるのは
timeout ミリ秒が経過した場合、 または num_initial_members 応答が受信された場合です。
27.1.3.2. TCPGOSSIP
TCPGOSSIP プロトコルは GossipRouter とのみ動作します。 基本的には有効な
gossip_host と gossip_port の属性を持つ PING プロトコル設定と同じように動作します。 UDP および TCP 両方のトランスポートプロトコルの上で動作します。 例を示します。
<TCPGOSSIP timeout="2000"
num_initial_members="3"
initial_hosts="192.168.5.1[12000],192.168.0.2[12000]"/>TCPGOSSIP 要素内で使用できる属性は以下の通りです。
- timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
- num_initial_members は、待機する最大応答数を指定します (タイムアウトが経過していない場合)。デフォルト値は 2 です。
- initial_hosts は
GossipRouterが登録するアドレスやポートのコンマで区切りリストしたものです (例:host1[12345],host2[23456])。
27.1.3.3. TCPPING
TCPPING プロトコルは既知のメンバーのセットをとり、 ディスカバリのため ping を行います。 これは基本的には静的な設定です。 TCP の上で動作します。 次に JGroups
config 要素内の TCPPING 設定要素の例を示します。
<TCPPING timeout="2000"
num_initial_members="3"/
initial_hosts="hosta[2300],hostb[3400],hostc[4500]"
port_range="3">
TCPPING 要素で使用できる属性は以下の通りです。
- timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
- num_initial_members は、待機する最大応答数を指定します (タイムアウトが経過していない場合)。デフォルト値は 2 です。
- initial_hosts は ping を行うアドレスのコンマ区切りリストです (例:
host1[12345],host2[23456])。 - port_range は、 初回のメンバーシップを取得する時に、
initial_hostsパラメータに指定されたポートよりプローブされる連続ポートの数を指定します。 上記のport_rangeとinitial_hostsの値を例とすると、TCPPING層 はhosta[2300]、hosta[2301]、hosta[2302]、hostb[3400]、hostb[3401]、hostb[3402]、hostc[4500]、hostc[4501]、hostc[4502]へ接続しようとします。 この設定オプションにより、 ポートの組み合わせをすべて記述しなくても同じホストの複数のポートへ ping することができます。 TCP プロトコル設定で、end_portがstart_portより大きい場合、 TCPPINGport_rangeがこの差異になるようにし、 許可範囲内でバインドされるポートに関係なくノードが ping されるようにすることが推奨されます。
27.1.3.4. MPING
MPING は IP マルチキャストを使用して最初のメンバーシップをディスカバリします。 ネットワーク上でのディスカバリメッセージの送受信をトランスポートプロトコルへ委譲する他とディスカバリプロトコルと違い、 MPING はソケットを開いてマルチキャストディスカバリメッセージを送受信します。 そのため、 すべてのトランスポートに使用できますが、 TCP で最も頻繁に使用されます。 通常、 TCP は可能性があるグループメンバーすべてを明示的にリストする必要がある TCPPING を必要とし、 標準のメッセージトランスポートに TCP が必要で、ディスカバリに UDP マルチキャスティングが許可される場合に使用されます。
<MPING timeout="2000"
num_initial_members="3"
bind_to_all_interfaces="true"
mcast_addr="228.8.8.8"
mcast_port="7500"
ip_ttl="8"/>
MPING 要素で使用できる属性は以下の通りです。
- timeout はなんらかの応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
- num_initial_members は待機する最大応答数を指定します (タイムアウトが経過しない場合)。デフォルト値は 2 です。
- bind_addr はメッセージの送受信を行うインターフェースを指定します。 デフォルトでは、 JGroups はシステムプロパティ
jgroups.bind_addrの値を使用します。-bコマンドラインスイッチを使用して設定することもできます。 JGroups ソケットのバインドに関する詳細は、 「その他設定の問題」 を参照してください。 - bind_to_all_interfaces は
bind_addrを上書きして multihome ノードにある全インターフェースを使用します。 - mcast_addr, mcast_port, ip_ttl 属性は UDP プロトコル設定にある関連属性と同じものになります。
27.1.4. 障害検出プロトコル
障害検出プロトコルは障害が発生したノードの検出に使用されます。 障害が発生したノードが検出されると、 検証フェーズが開始されます。 このフェーズが終了してもノードがまだダウンしていると見なされた場合は、 クラスターがそのビューを更新し、 メッセージが障害が発生したノードに送信されないようにします。 ノードがクラスターの一部でなくなったことが JGroups を使用するサービスに報告されます。 障害検出プロトコルは JGroups
<config> 要素内のサブ要素として設定されます。
27.1.4.1. FD
FD は「ハートビート」メッセージに基づく障害検出プロトコルです。このプロトコルでは各ノードが定期的に近くのノードに ping する必要があります。近くのノードが応答しないと、呼び出しするノードは SUSPECT メッセージをクラスターに送ります。現在のグループコーディネータは、この疑いのあるノードが実際に停止しているか (VERIFY_SUSPECT) 任意に検証できます。この検証段階の後にまだノードがダウンしている場合、コーディネータがクラスターのビューを更新します。FD 設定の例は次の通りです。
<FD timeout="6000"
max_tries="5"
shun="true"/>
FD 要素で使用できる属性は以下の通りです。
- timeout は are-you-alive メッセージに対する応答を待機する最大ミリ秒数を指定します。デフォルト値は 3000 です。
- max_tries はノードが疑われるまでそのノードから失った are-you-alive メッセージの数を指定します。デフォルト値は 2 です。
- shun は、障害のあるノードが正式にグループに再参加せずにそのグループへのメッセージ送信を不可にするかどうかを指定します。回避されたノードはディスカバリプロセスを通じてクラスターに再参加しなければならなくなります。チャネルが回避されると自動的に再参加やステート移動が発生するよう JGroups を設定することができます (これは JBoss Application Server のデフォルトの動作です)。
注記
ノードからの定期的なトラフィックはノードが生存している証拠となります。 このため、長期間ノードに定期的なトラフィックが検出されなかった場合のみハートビートメッセージが送信されます。
27.1.4.2. FD_SOCK
FD_SOCK は、 グループメンバ間で作成された TCP ソケットのリングに基づく障害検出プロトコルです。 グループ内の各メンバは近くのメンバに接続し (最後のメンバは最初のメンバに接続します)、 リングを形成します。 ノード B の近くにある ノードA は、 正常に閉じられなかった TCP ソケットを検出した時にノード B を疑い、 ノード B のクラッシュが原因であると想定します (ノードがグループから退出しようとすると、 近くのノードに連絡し、 近くのノードが疑われないようにします)。
最も単純な
FD_SOCK 設定は属性を使用しません。 JGroups <config> 要素に空の FD_SOCK 要素を宣言できます。
<FD_SOCK/>
FD_SOCK 要素に使用できる属性は次の通りです。
- bind_addr はメッセージの送受信を行うインターフェースを指定します。 デフォルトでは、 JGroups はシステムプロパティ
jgroups.bind_addrの値を使用します。-bコマンドラインスイッチを使用して設定することもできます。 JGroups ソケットのバインドに関する詳細は、 「その他設定の問題」 を参照してください。
27.1.4.3. VERIFY_SUSPECT
このプロトコルは、疑いのあるメンバが実際にダウンしているかそのメンバーに対してもう一度 ping を実行して確認します。この確認は、クラスターのコーディネータによって実行されます。疑いのあるメンバはダウンしていることが確認されるとクラスタグループから破棄されます。このプロトコルの目的は、間違った疑いを最小限に抑えることです。以下に例を示します。
<VERIFY_SUSPECT timeout="1500"/>
VERIFY_SUSPECT 要素に使用できる属性は次の通りです。
- timeout は、 疑いのあるメンバーの応答を待つ時間を指定します。 この待ち時間を過ぎるとダウンしていると見なされます。
27.1.4.4. FD と FD_SOCK
FD と FD_SOCK (それぞれ独立して取得) では、障害検出レイヤーは安定していません。では、これらの障害検出プロトコル間の違いを把握し、これらがお互いどのように補完するかについて理解していきましょう。
- FD
- 過負荷の状態にあるマシンは、are-you-alive 応答の送信時にパフォーマンスが低下することがあります。
- デバッガ/プロファイラーでサスペンドされたときに、メンバーに問題があるのではと疑いがかけられます。
- タイムアウトを小さくすると、誤検出の可能性が大きくなり、ネットワークトラフィックが増大します。
- タイムアウトが大きいと、クラッシュしたメンバーが一定の時間検出されず、破棄されません。
- FD_SOCK:
- TCP 接続はまだオープンなのでデバッガでサスペンドされても問題ありません。
- 同様の理由により、高ロードも問題とはなりません。
- TCP 接続が中断された場合メンバーに疑いがかけられ、停止しているメンバーは検出されません。
- また、クラッシュしたスイッチは、接続が TCP タイムアウト (2〜20 分。TCP/IP スタック実装によって異なる) になるまで検出されません。
障害検出層の目的は、 実際の障害を迅速に報告し、 誤った疑いをかけないようにすることです。 2 つの解決法が存在します。
- デフォルトでは、JGroups は KEEP_ALIVE で FD_SOCK ソケットを設定します。これは、TCP が、トラフィックを 2 時間受信していないソケットにハートビートを送信することを意味します。TCP 接続を適切に閉じずにホストがクラッシュすると (または中間スイッチまたはルーターがクラッシュすると)、2 時間 (プラス数分) 後にこれを検出することになります。これは、当然接続をまったく閉じないよりもいいですが (KEEP_ALIVE が無効な場合)、それほど役に立たないことおあります。したがって、最初の解決法は、KEEP_ALIVE のタイムアウト値を小さくすることです。これは、ほとんどのオプションではカーネル全体に対してのみ行えます。したがって、この値を 15 分まで小さくすると、すべての TCP ソケットが影響を受けます。
- 2 つ目の解決法は FD_SOCK と FD を組み合わせることです。FD のタイムアウトは TCP タイムアウトよりもかなり小さくなるよう設定できます。これは 1 つのプロセスごとに個別に設定できます。ソケットが正常に閉じられていない場合は FD_SOCK が疑いがあることを示すメッセージを生成します。ただし、クラッシュしたスイッチまたはホストの場合は、FD によって、ソケットが結果的に閉じられ、疑いがあることを示すメッセージが生成されるようになります。以下に例を示します。
<FD_SOCK/> <FD timeout="6000" max_tries="5" shun="true"/> <VERIFY_SUSPECT timeout="1500"/>
この例では、 オペレーティングシステムがすべてのソケットを閉じるため、 近くにあるソケットがクラッシュなどで正常に閉じられなかった時にメンバーが疑われます。 ただし、 ホストまたはスイッチがクラッシュすると、 ソケットは閉じられません。
FD は 60 秒後 (6000 ミリ秒) 後に近くのメンバを疑います。 この例では、 デバッガのブレークポイントでシステムが停止した場合、 timeout が経過した後にデバッグされたノードが疑われます。
FD と FD_SOCK の組み合わせにより、 安定した障害検出層が提供されます。 このため、 この技術は JBoss Application Server に含まれる JGroups 設定全体で使用されます。
27.1.5. 信頼できる配信プロトコル
JGroups スタック内の信頼できる配信プロトコルはデータパケットが実際に正しい順序 (FIFO) で目的地となるノードに配信されるようにします。 肯定的および 否定的な配信確認 (ACK と NAK) が信頼できるメッセージ配信の基盤となります 。
ACK モードでは、 送信側が受信側からの確認が受信されるまでメッセージを再送します。 NAK モードでは、 受信側がギャップを発見した場合に再送を要求します。
27.1.5.1. UNICAST
UNICAST プロトコルはユニキャストメッセージに使用されます。 肯定的な確認を使用し (ACK)、JGroups config 要素のサブ要素として設定されます。 JGroups スタックが TCP トランスポートプロトコルで設定された場合は、 TCP 自体がユニキャストメッセージの FIFO 配信を保証するため UNICAST は必要ありません。 次に、UNICAST プロトコルの設定例を示します。
<UNICAST timeout="300,600,1200,2400,3600"/>
UNICAST 要素で設定できる属性は 1 つのみです。
- timeout は、 再送信のタイムアウト (ミリ秒単位) を指定します。 例えば、 タイムアウトが
100,200,400,800の場合、 最初 100 ミリ秒後にACKを受信しなかったら送信元がメッセージを再送信し、 2 回目の再送信を行う前に 200 ミリ秒待ちます。 最初のタイムアウト値を小さくすると、 損失したメッセージの再送信が迅速に行われますが、 実際にメッセージを損失しなかった場合は、 メッセージが複数回送信されます (メッセージは送信されても 、ACKがタイムアウト前に受信されなかった場合)。 UDP データグラムが頻繁に損失しないようネットワークが調整されている場合、 大きな値 (1000,2000,3000) を設定するとパフォーマンスは改善されます。 損失が頻発するネットワークに大きな値を設定すると、 損失したメッセージが再送信されるまで後のメッセージが発信されないため、 パフォーマンスに悪影響を与えます。
27.1.5.2. NAKACK
NAKACK プロトコルはマルチキャストメッセージに使用されます。 否定的な確認 (NAK) を使用します。 このプロトコルでは、 各メッセージは連続番号のタグが付けられます。 受信者はこの連続番号を追跡して順序通りにメッセージを配信します。 受信した連続番号でギャップが検出されると、 周期的に損失したメッセージの再送信を送信者に依頼するタスクを受信先が設定します。 損失したメッセージが受信されると、このタスクはキャンセルされます。NAKACK プロトコルは JGroups <config> 要素配下の pbcast.NAKACK サブ要素として設定されます。 設定例は次の通りです。
<pbcast.NAKACK max_xmit_size="60000" use_mcast_xmit="false" retransmit_timeout="300,600,1200,2400,4800" gc_lag="0" discard_delivered_msgs="true"/>
pbcast.NAKACK 要素で設定できる属性は以下の通りです。
- retransmit_timeout は、一連のタイムアウト時間 (ミリ秒単位) を指定します。 ここで指定したタイムアウト時間以降に、 損失したメッセージが受信されないと再送信が要求されます。
- use_mcast_xmit は送信者が再送を要求しているノードだけではなくクラスター全体に再送信すべきであるか判断します。 送信者のネットワーク層でパケット落ちが発生する傾向にある場合に便利で、各ノードごとに再送信する必要がありません。
- max_xmit_size は複数メッセージの損失が報告がされた時のバンドル再送信の最大サイズ (バイト単位) を指定します。
- discard_delivered_msgs は受信者ノードで配信されたメッセージを破棄するかを指定します。 デフォルトでは、 ノードが配信されたメッセージを保存するため、 元の送信者がクラッシュあるいはグループを退出してもすべてのノードが損失したメッセージを再送信することができます。ただし、 送信者のみにそのメッセージを再送するよう依頼する場合は、 このオプションを有効にして配信されたメッセージを破棄することができます。
- gc_lag は、 周期的なクリーンアッププロトコル (「分散ガベージコレクション (STABLE)」 参照) がすべてのピアがメッセージを受信したと提示した場合でも、 再送信のためにメモリに保持するメッセージの数を指定します。 デフォルト値は
20です。
27.1.6. グループメンバーシップ (GMS)
JGroups スタック内のグループメンバーシップサービス (GMS) はアクティブなノードの一覧を管理しています。 クラスターへの参加および退出の要求を処理します。 また、 障害検出プロトコルから送信される SUSPECT メッセージも処理します。 クラスタ内のすべてのノードや、JBoss Cache および HAPartition などの関心のあるサービスは、グループメンバーシップが変更されると通知を受けます。 グループメンバーシップサービスは JGroups
config 要素配下の pbcast.GMS サブ要素に設定されます。 設定例は次の通りです。
<pbcast.GMS print_local_addr="true"
join_timeout="3000"
join_retry_timeout="2000"
shun="true"
view_bundling="true"/>
pbcast.GMS 要素で設定できる属性は以下の通りです。
- join_timeout 新しいノードの JOIN 要求が成功するの待つ最長ミリ秒数を指定します。 指定ミリ秒数経過後は再び試行します。
- join_retry_timeout は、 JOIN が失敗した後、 再試行するまでに待機する時間 (ミリ秒単位) を指定します。
- print_local_addr は起動時のノード自体のアドレスを標準出力にダンプするかを指定します。
- shun は、メンバーノードではないクラスタービューを受信した場合にノード自身が shun (切断) を行うかどうかを指定します。
- disable_initial_coord は、最初にチャネルへ接続する際に、ノードがクラスターコーディネーターになることを阻止するか指定します。 現在のコーディネーターがグループから退出した場合、 最初のチャネル接続の後にノードがコーディネーターになることを阻止することはできません。
- view_bundling は、同時に到着した複数の JOIN 要求や LEAVE 要求をまとめて同時に処理し、1 つの新しいビューのみがすべての変更を反映するようにするかを指定します。これは、各要求を別々に処理するよりも効率的です。
27.1.7. フロー制御 (FC)
フロー制御(FC) プロトコルはノード間でデータ送信率をデータ受信率へ適応させようとします。 送信側ノードが速すぎる場合、 受信側ノードが対応できないため、メモリ不足になるか、再送信されたパケットがドロップされることがあります。JGroups では、 フロー制御はクレジットベースのシステムで実装されます。 送受信ノードは同じクレジット数 (バイト) を開始時に持っています。 送信側は送信するメッセージのバイト数をクレジットから引きます。 受信側は受信するメッセージのバイトをクレジットに足します。 送信側のクレジットがしきい値まで減少すると、 受信側は送信側にクレジットを送ります。 送信側のクレジットがなくなると、 受信側からクレジットを受け取るまで送信側はブロックします。 フロー制御プロトコルは JGroups
config 要素配下の FC サブ要素に設定されます。 設定例は次の通りです。
<FC max_credits="2000000"
min_threshold="0.10"
ignore_synchronous_response="true"/>
FC 要素で使用できる属性は以下の通りです。
- max_credits はクレジット (バイト単位) の最大数を指定します。 この値は JVM ヒープサイズより小さくしてください。
- min_credits は、 受信側が送信側にクレジットを送付する前に受け取らなければならない最低バイト数を指定します。
- min_threshold は、
min_creditsを算出するために使用するmax_creditsの割合 (パーセント) を指定します。 この設定はmin_credits属性よりも優先されます。 - ignore_synchronous_response は、 アプリケーションへメッセージを運んだスレッドが、 クレジットをブロックせずに FC より送信メッセージを運び戻すことができるようにするかを指定します。 同期応答とは、 通常これらのメッセージが受信 RPC タイプのメッセージの応答であることを意味しています。 JGroups スレッドが FC のブロックへメッセージを運べないようにすると、 特定のデッドロックを防ぐことができるため、
trueに設定することが推奨されます。
注記
最も低速の受信先が処理できる最速の速さでグループメッセージを送信しなければならない場合、 グループ通信に FC が必要となります。 例えば、 ノード A、 B、 C、D で構成されるクラスターがあるとします。 D は低速で (オーバーロードの可能性)、 他のノードはすべて高速だとします。 A がグループメッセージを送信する場合、 TCP 接続より A-A (理論上)、 A-B、 A-C、 A-D のように送信されます。
例えば、A がクラスターへ 1 億通のメッセージを送信するとしましょう。 TCP のフロー制御は個別に A-B、 A-C、 A-D へ適用されますが、 A-BCD へグループとしては適用されません。 そのため、 A、 B、C は 1 億通のメッセージを受信しますが、 D は 100 万通のメッセージのみを受信します (そのため、TCP が独自の再送信を処理しても
NAKACK が必要となるのです)。
JGroups は、 元の送信側 S がダウンし、S が送信したメッセージの再送信をノードがリクエストしたときに備え、メモリ内のすべてのメッセージをバッファーする必要があります。 すべてのメンバは受信したすべてのメッセージをバッファするため、 安定したメッセージ (すべてのノードが可視できるメッセージ) を時々消去する必要があります (消去のプロセスは
STABLE プロトコルによって管理されます。 詳細は 「分散ガベージコレクション (STABLE)」 を参照してください)。
上記のケースでは、 低速なノード D によってグループが 1M を超えるメッセージを消去することができず、 各メンバが 99M メッセージをバッファーします。 ほとんどの場合、 これにより OOM 例外が発生します。 TCP のスライドウィンドウプロトコルではウィンドウがいっぱいである場合書き込みがブロックされますが、上記のケースでは A-D よりも A-B と A-C の方が高速であると見なすことに注意してください。
そのため、 最も低速な受信側 (D) が処理できる速度でメッセージを送信する必要があるため、 TCP を使用していても FC が必要となります。
注記
これは、アプリケーションが JGroups チャネルをどのように使用するかによって異なります。上記の例では、 D が対応できないため、 A が送信レートを下げるアプリケーションの場合に FC は必要なくなります。
このようなアプリケーションの良い例として、 同期グループ RPC 呼び出しを行うアプリケーションがあります。 ここで同期とは、 呼び出しするスレッドがグループのすべてのメンバからの応答待機をブロックすることを意味します。 このようなアプリケーションでは、 呼び出しを行う A のスレッドが D からの応答の待機をブロックし、 全体的な呼び出しの速度を自然に低下させます。
REPL_SYNC に設定された JBoss Cache クラスターは同期グループ RPC 呼び出しを行うアプリケーションの良い例です。 チャネルが REPL_SYNC に設定されたキャッシュに対してのみ使用される場合は、プロトコルスタックから FC を削除することをお勧めします。
また、 当然クラスターが 2 つのノードのみから構成される場合は、 FC を TCP ベースのプロトコルスタックに含めることは必要ありません。 単一のピアツーピア関係を超えるグループは存在せず、 TCP の内部フロー制御はこれを適切に処理します。
FC が必要ではない別のケースは、 バディレプリケーションと単一バディに対して設定された JBoss Cache により使用されるチャネルを使用する場合です。 このようなチャネルは多くの点で 2 ノードクラスターのように動作し、 メッセージはもう 1 つのノード (バディ) とのみ交換されます (すべてのメンバに送信されるデータグラビテーションに関する他のメッセージが存在する場合がありますが、 適切に設計されたバディレプリケーションのケースではそのようなことはほとんどありません。 ただし、 FC を削除する場合はアプリケーションの負荷をテストしてください)。