第5章 ネットワーク接続
5.1. 自動フェイルオーバー
クライアントは、接続障害が発生した場合にスレーブブローカーに再接続できるように、すべてのマスターおよびスレーブブローカーに関する情報を受け取ることができます。その後、スレーブブローカーは、フェイルオーバー前に各接続に存在したセッションおよびコンシューマーを自動的に再作成します。この機能により、アプリケーションで手動で再接続ロジックをコーディングする必要がなくなります。
セッションがスレーブで再作成されると、送信または確認済みのメッセージを認識しません。フェイルオーバー時の in-flight の送信と確認応答も失われる可能性があります。ただし、透過的なフェイルオーバーがなくても、トランザクションの重複検出と再試行の組み合わせを使用することで、障害が発生した場合でも、一度だけ の配信を保証するのは簡単です。
クライアントは、設定可能な期間内にブローカーからパケットを受信しないと接続の障害を検出します。詳細は、「デッド接続の検出」 を参照してください。
マスターおよびスレーブについての情報を受信するようにクライアントを設定する方法は複数あります。1 つのオプションとして、特定のブローカーに接続し、クラスター内の他のブローカーに関する情報を受信するようにクライアントを設定します。詳細は、「静的検出の設定」 を参照してください。ただし、最も一般的な方法は、ブローカー検出 を使用することです。ブローカー検出の設定方法の詳細は、「動的検出の設定」 を参照してください。
また、以下の例のように、ブローカーへの接続に使用される URI のクエリー文字列にパラメーターを追加して、クライアントを設定することもできます。
connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&reconnectAttempts=3
connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&reconnectAttempts=3
手順
クエリー文字列を使用してフェイルオーバーを行うようにクライアントを設定するには、URI の以下のコンポーネントが適切に設定されていることを確認します。
-
URI の
host:port
の部分は、バックアップで適切に設定されたマスターブローカーを参照する必要があります。このホストおよびポートは最初の接続にのみ使用されます。host:port
の値は、ライブサーバーとバックアップサーバー間の実際の接続フェイルオーバーとは関係ありません。上記の例では、localhost:61616
がhost:port
に使用されます。 (オプション) 複数のブローカーを可能な初期接続として使用するには、以下の例のように
host:port
エントリーをグループ化します。connectionFactory.ConnectionFactory=(tcp://host1:port,tcp://host2:port)?ha=true&reconnectAttempts=3
connectionFactory.ConnectionFactory=(tcp://host1:port,tcp://host2:port)?ha=true&reconnectAttempts=3
Copy to Clipboard Copied! -
名前/値のペア
ha=true
をクエリー文字列の一部として追加し、クライアントがクラスター内の各マスターおよびスレーブブローカーに関する情報を受け取るようにします。 -
名前と値のペア
reconnectAttempts=n
を含めます。n
は、0
より大きい整数です。このパラメーターは、クライアントがブローカーへの再接続を試行する回数を設定します。
フェイルオーバーは ha=true
と reconnectAttempts
が 0
よりも大きい場合にのみ発生します。また、他のブローカーに関する情報を取得するために、クライアントはマスターブローカーへ最初の接続を確立する必要があります。最初の接続に失敗すると、クライアントは再試行して接続を確立できます。詳細は、「初期接続時のフェイルオーバー」 を参照してください。
5.1.1. 初期接続時のフェイルオーバー
クライアントは HA クラスターへの最初の接続が確立されるまですべてのブローカーに関する情報を受け取らないため、クライアントが接続 URI に含まれるブローカーにのみ接続できる期間があります。したがって、この最初の接続で障害が発生した場合、クライアントは他のマスターブローカーにフェイルオーバーできず、最初の接続の再確立のみを試すことができます。クライアントには、再接続試行回数を設定できます。試行がその回数行われると、例外が出力されます。
再接続試行回数の設定
手順
以下の例は、AMQ Core Protocol JMS クライアントを使用して再接続試行回数を 3
に設定する方法を示しています。デフォルト値は 0
で、つまり、1 回のみ試行します。
ServerLocator.setInitialConnectAttempts()
に値を渡して、再接続試行の数を設定します。ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactory(...) cf.setInitialConnectAttempts(3);
ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactory(...) cf.setInitialConnectAttempts(3);
Copy to Clipboard Copied!
再接続試行回数のグローバル設定
または、ブローカーの設定内で再接続試行回数のグローバルな値を適用できます。最大値はすべてのクライアント接続に適用されます。
手順
以下の例のように、
<broker-instance-dir>/etc/broker.xml
を編集してinitial-connect-attempts
設定要素を追加し、time-to-live の値を指定します。<configuration> <core> ... <initial-connect-attempts>3</initial-connect-attempts> ... </core> </configuration>
<configuration> <core> ... <initial-connect-attempts>3</initial-connect-attempts>
1 ... </core> </configuration>
Copy to Clipboard Copied! - 1
- ブローカーに接続するすべてのクライアントは、最大 3 回の再接続の試行が許可されます。デフォルトは
-1
で、クライアントは無制限の試行を許可します。
5.1.2. フェイルオーバー中のブロック呼び出しの処理
フェイルオーバーが発生し、クライアントが実行を継続するためにブローカーからの応答を待機している場合、新たに作成されたセッションには、進行中の呼び出しに関する情報がありません。初期呼び出しは、それ以外では、決して受け取ることのない応答を待機してハングする可能性があります。これを防ぐため、ブローカーは例外を出力することで、フェイルオーバー時に進行中のブロッキング呼び出しのブロックを解除するように設計されています。クライアントコードはこれらの例外をキャッチし、必要に応じてすべての操作を再試行できます。
AMQ Core Protocol JMS クライアントを使用する場合、ブロックされていないメソッドが commit()
または prepare()
の呼び出しである場合、トランザクションは自動的にロールバックされ、ブローカーによって例外が発生します。
5.1.3. トランザクションによるフェイルオーバーの処理
AMQ Core Protocol JMS クライアントを使用すると、セッションがトランザクションであり、現在のトランザクションでメッセージがすでに送信または確認応答されている場合、ブローカーはフェイルオーバー中にメッセージまたはその確認応答が失われたかどうかがわかりません。そのため、トランザクションはロールバック用にのみマークされます。その後、コミットしようとすると javax.jms.TransactionRolledBackException
が出力されます。
このルールに関する注意点は、XA を使用する場合です。2 フェーズコミットが使用され、prepare()
がすでに呼び出されている場合、ロールバックによって HeuristicMixedException
が発生する可能性があります。このため、コミットによって XAException.XA_RETRY
例外が発生し、トランザクションマネージャーは後でコミットを再試行することを通知します。元のコミットが発生していない場合、それはまだ存在し、コミットされます。存在しない場合、コミットされたと見なされますが、トランザクションマネージャーが警告を記録する可能性があります。この例外の副次的な影響は、非永続的なメッセージが失われることです。このような損失を回避するために、XA を使用する際には常に永続メッセージを使用してください。prepare()
が呼び出される前にサーバーにフラッシュされるため、これは確認応答の問題ではありません。
AMQ Core Protocol JMS クライアントコードは、例外をキャッチし、必要なクライアント側のロールバックを実行する必要があります。ただし、セッションはロールバックされているため、セッションをロールバックする必要はありません。ユーザーは、同じセッションに対してトランザクション操作を再試行できます。
コミット呼び出しの実行時にフェイルオーバーが発生すると、ブローカーは呼び出しをブロックしず、AMQ Core Protocol JMS クライアントが応答を無期限に待機しないようにします。この場合、障害が発生する前にトランザクションのコミットがライブサーバーで実際に処理されたかどうかをクライアントが判断するのは容易ではありません。
これを修正するには、AMQ Core Protocol JMS クライアントはトランザクションで重複検出を有効にし、呼び出しがブロック解除された後にトランザクション操作を再試行します。フェイルオーバー前にトランザクションが正常にマスターブローカーでコミットされた場合、重複検出により、再試行時にトランザクションに存在する永続メッセージがブローカー側で無視されるようにします。これにより、メッセージが複数回送信されなくなります。
セッションがトランザクションではない場合は、フェイルオーバー時にメッセージまたは確認応答が失われる可能性があります。トランザクション以外のセッションに 一度だけ 配信する保証を提供する場合は、重複検出を有効にし、ブロック解除例外をキャッチします。
5.1.4. 接続失敗の通知
JMS は、接続障害の非同期に通知するための標準メカニズムである java.jms.ExceptionListener
を提供します。
ExceptionListener
または SessionFailureListener
インスタンスは、接続が正常にフェイルオーバー、再接続、または再割り当てされたかどうかに関係なく、接続障害が発生した場合にブローカーによって常に呼び出されます。SessionFailureListener
の connectionFailed
で渡された failedOver
フラグを調べると、再接続または再割り当てが発生したかどうかを確認できます。または、javax.jms.JMSException
のエラーコードを確認できます。これは以下のいずれかになります。
エラーコード | 説明 |
---|---|
FAILOVER | フェイルオーバーが発生し、ブローカーが正常に再割り当てまたは再接続しました。 |
DISCONNECT | フェイルオーバーは発生せず、切断されています。 |