第18章 Messaging
18.1. はじめに
18.1.1. HornetQ
HornetQ は、Red Hat により開発されたマルチプロトコル非同期メッセージングシステムです。HornetQ は、サーバーに障害が発生した場合のメッセージの信頼性を保証するために、自動クライアントフェイルオーバーで高可用性(HA)を提供します。HornetQ は、負荷分散されたメッセージで柔軟なクラスタリングソリューションもサポートします。
HornetQ は JBoss EAP 6 の Java Message Service(JMS)プロバイダーで、
メッセージングサブシステム
として設定されます。
18.1.2. 低速な HornetQ コンシューマーの処理
サーバー側のキュー(JMS トピックサブスクライバーなど)を持つ低速なコンシューマーは、ブローカーのパフォーマンスに大きな問題を引き起こす可能性があります。メッセージがコンシューマーのサーバー側のキューで構築されると、メモリーは一杯になり、ブローカーはページングモードになり、パフォーマンスに悪影響を及ぼす可能性があります。ただし、メッセージをすぐに確認しないコンシューマーをブローカーから切断できるように基準を設定できます。この場合、非永続的な JMS サブスクライバーの場合、ブローカーがサブスクリプションを削除し、そのメッセージすべてで有用なサーバーリソースを解放できます。
18.1.3. フェイルオーバー中のブロック呼び出しの処理
クライアントコードがサーバーへのブロック呼び出しにあり、実行を継続する応答を待つと、フェイルオーバーが発生すると、新しいセッションには、進行中の呼び出しに関する知識はありません。そうでないと、この呼び出しはハングし、到達しない応答を待つ可能性があります。
これを防ぐため、HornetQ は、JMS を使用する場合は
javax.jms.JMSException
をスローし、エラーコード HornetQException.UNBLOCKED
のある HornetQException
をスローすることにより、フェイルオーバー時に進行中のブロッキング呼び出しのブロックを解除します。この例外をキャッチし、必要に応じて操作を再試行するかどうかはクライアントコード次第です。
ブロック解除されるメソッドが commit()または prepare()の呼び出しである場合、トランザクションは自動的にロールバックされ、HornetQ は(JMS を使用する場合)
javax.jms.TransactionRolledBackException
をスローし、コア API を使用する場合はエラーコード HornetQException
.TRANSACTION_ROLLED_BACK
を設定して HornetQException をスローします。
18.1.4. トランザクションによるフェイルオーバーの処理
セッションがトランザクションであり、現在のトランザクションでメッセージがすでに送受信された場合、サーバーはフェイルオーバー中に送受信されたメッセージが失われていないことを確認できません。
そのため、トランザクションはロールバック専用としてマークされ、その後コミットしようとすると
javax.jms.TransactionRolledBackException
(JMS を使用している場合は)をスローし、コア API を使用する場合はエラーコード HornetQException
.TRANSACTION_ROLLED_BACK
を設定して HornetQException をスローします。
例外をキャッチし、必要に応じてクライアント側のローカルロールバックコードを実行するのはユーザー次第です。セッションを手動でロールバックする必要はありません。すでにロールバックされています。その後、ユーザーは同じセッションでトランザクション操作を再試行できます。
コミット呼び出しの実行中にフェイルオーバーが発生すると、前述したようにサーバーが応答を返さないため、ハングを防ぐために呼び出しのブロックを解除します。この場合、障害が発生する前にトランザクションのコミットがライブサーバーで実際に処理されたかどうかをクライアントが判断するのは容易ではありません。
これを修正するには、クライアントはトランザクションで重複検出を有効にし、呼び出しがブロック解除された後にトランザクション操作を再試行します。フェイルオーバー前にトランザクションが実際にライブサーバーで正常にコミットされた場合、トランザクションが再試行されると、重複検出により、トランザクションで再送信された永続メッセージがサーバーで無視され、それらが複数回送信されないようにします。
注記
ロールバック例外をキャッチして再試行すると、ブロックされていない呼び出しをキャッチし、重複検出を有効にすることで、1 回限りの配信保証は、メッセージに障害が発生した場合に提供でき、100% の損失や重複の保証が保証されます。
18.1.5. 非トランザクションセッションを使用したフェイルオーバーの処理
セッションがトランザクションではない場合、フェイルオーバー時にメッセージまたは確認応答が失われる可能性があります。
トランザクション以外のセッションに、1 回限りの配信保証を提供し、重複検出を有効にし、ブロック解除例外をキャッチします。
18.1.6. 接続失敗の通知
JMS は、接続障害の非同期に通知する標準メカニズムを提供します(
java.jms.ExceptionListener
)。ExceptionListener の詳細は、Oracle javax.jms Javadoc を参照してください。
HornetQ コア API は、
org.hornet.core.client.SessionFailureListener
クラスの形式で同様の機能も提供します。
JMS
ExceptionListener
または Core SessionFailureListener
インスタンスは、接続が正常に失敗したか、再接続または再アタッチされたかどうかに関係なく、接続障害が発生した場合に常に HornetQ によって呼び出されます。
18.1.7. Java Messaging Service (JMS)
メッセージングシステムにより、異種システムを疎結合して、信頼性も高めることができます。Java Messaging Service(JMS)プロバイダーはトランザクションのシステムを使用して、変更をアトミックにコミットまたはロールバックします。Remote Procedure Call (RPC) パターンに基づいたシステムとは異なり、メッセージングシステムは、リクエストと応答の間に密接な関係がないパターンを渡す非同期メッセージを主に使用します。ほとんどのメッセージングシステムは request-response モードもサポートしますが、メッセージングシステムの主な機能ではありません。
メッセージングシステムはメッセージのコンシューマーからメッセージの送信者を切り離します。メッセージの送信者とコンシューマーは完全に独立しており、相互に何も知りません。これにより、柔軟に結合されたシステムを作成できます。多くの場合、大規模な企業ではメッセージングシステムを使用して、異種システムを結合するメッセージバスを実装します。メッセージバスは、Enterprise Service Bus(ESB)の中核を形成することがよくあります。メッセージバスを使用して異種システムを切り離すことで、システムを拡大し、より容易に適応させることができます。また、不安定な依存関係がないため、より柔軟に新しいシステムを追加したり、古いシステムを廃止したりできます。
18.1.8. サポートされているメッセージ形式
HornetQ は、以下のメッセージ形式に対応しています。
- Message Queue パターン
- Message Queue パターンでは、メッセージをキューに送信する必要があります。キューに入ると、通常、メッセージは永続化され、配信が保証されます。メッセージがキューを通過すると、メッセージングシステムはメッセージコンシューマーに配信します。メッセージコンシューマーは、処理後にメッセージの配信を確認します。Message Queue パターンでは、ポイントツーポイントメッセージングと併用すると、複数のコンシューマーをキューに入れることが可能ですが、各メッセージは単一のコンシューマーのみが受信可能となります。
- Publish-Subscribe パターン
- Publish-Subscribe パターンにより、複数の送信者がサーバー上の単一のエンティティーにメッセージを送信できます。このエンティティーは、「トピック」と呼ばれることがよくあります。各トピックは、「サブスクリプション」と呼ばれる複数のコンシューマーによって参加できます。各サブスクリプションは、トピックに送信されたすべてのメッセージのコピーを受け取ります。これは、各メッセージが単一のコンシューマーによってのみ消費される Message Queue パターンとは異なります。永続的なサブスクリプションは、サブスクライバーが消費するまで、トピックに送信された各メッセージのコピーを保持します。これらのコピーは、サーバーの再起動時にも保持されます。非永続的なサブスクリプションは、それらを作成した接続のみを保持します。