6.3. Dead Letter Channel
概要 リンクのコピーリンクがクリップボードにコピーされました!
図6.3「Dead Letter Channel パターン」 で示されている Dead Letter Channel パターンは、メッセージングシステムが目的の受信者にメッセージを配信できない場合に実行するアクションを記述します。これには、配信を再試行する機能などが含まれ、最終的に配信に失敗した場合には、メッセージが Dead Letter Channel に送信され、未達のメッセージをアーカイブします。
図6.3 Dead Letter Channel パターン
Java DSL でのデッドレターチャネルの作成 リンクのコピーリンクがクリップボードにコピーされました!
以下の例は、Java DSL を使用してデッドレターチャネルを作成する方法を示しています。
errorHandler(deadLetterChannel("seda:errors"));
from("seda:a").to("seda:b");
errorHandler(deadLetterChannel("seda:errors"));
from("seda:a").to("seda:b");
errorHandler() メソッドは Java DSL インターセプターで、現在のルートビルダーで定義された すべて のルートがこの設定の影響を受けることを意味します。deadLetterChannel() メソッドは、指定の宛先エンドポイント seda:errors で新しいデッドレターチャネルを作成する Java DSL コマンドです。
errorHandler() インターセプターは、すべて のエラータイプを処理するためのキャッチオールメカニズムを提供します。例外処理により粒度の細かい方法を適用する場合は、代わりに onException 句を使用できます (「onException 句」 を参照)。
XML DSL の例 リンクのコピーリンクがクリップボードにコピーされました!
以下のように、XML DSL でデッドレターチャネルを定義できます。
再配信ポリシー リンクのコピーリンクがクリップボードにコピーされました!
通常、配信に失敗した場合、デッドレターチャネルに直接メッセージを送信することはありません。代わりに、最大限度まで再送信を試み、再配信の試行がすべて失敗した場合は、メッセージをデッドレターチャネルに送信します。メッセージの再配信をカスタマイズするには、デッドレターチャネルを設定して 再配信ポリシー を取得します。たとえば、再配信の最大試行回数を 2 回に指定し、配信試行間の遅延に指数バックオフアルゴリズムを適用するには、以下のようにデッドレターチャネルを設定できます。
errorHandler(deadLetterChannel("seda:errors").maximumRedeliveries(2).useExponentialBackOff());
from("seda:a").to("seda:b");
errorHandler(deadLetterChannel("seda:errors").maximumRedeliveries(2).useExponentialBackOff());
from("seda:a").to("seda:b");
ここでは、チェーンの関連メソッドを呼び出して、デッドレターチャネルに再配信オプションを設定します (チェーンの各メソッドは現在の RedeliveryPolicy オブジェクトの参照を返します)。表6.1「再配信ポリシーの設定」 には、再配信ポリシーの設定に使用できるメソッドがまとめられています。
| メソッドの署名 | デフォルト | 説明 |
|---|---|---|
|
|
| 正常なシャットダウン中またはルートが停止している間、再配信を試行するかどうかを制御します。すでに進行中の配信は停止時に中断され ません。 |
|
|
|
指数バックオフが有効な場合は、 d, m*d, m*m*d, m*m*m*d, ...
|
|
|
|
競合の回避が有効になっている場合は、 |
|
|
|
Camel 2.15: デッドレターチャネルでメッセージの処理中に発生する例外を処理するかどうかを指定します。 |
|
| なし | Apache Camel 2.0: 「Redeliver Delay パターン」 を参照してください。 |
|
|
|
Apache Camel 2.0: 再配信機能を無効にします。再配信を有効にするには、 |
|
|
|
Apache Camel 2.0: |
|
|
| 最初の再配信を試みるまでの遅延 (ミリ秒単位) を指定します。 |
|
|
| デッドレターチャネルで例外が発生した場合に WARN レベルでログに記録するかどうかを指定します。 |
|
|
|
Apache Camel 2.0: |
|
|
| Apache Camel 2.0: 配信の最大試行回数。 |
|
|
|
Apache Camel 2.0: 指数バックオフストラテジーを使用する場合 ( |
|
| なし | Apache Camel 2.0: 再配信を試みる前に呼び出されるプロセッサーを設定します。 |
|
|
| Apache Camel 2.0: 再配信の試行間の遅延 (ミリ秒単位) を指定します。Apache Camel 2.16.0: デフォルトの再配信遅延は 1 秒です。 |
|
|
|
Apache Camel 2.0: 配信の失敗をログに記録するログレベルを指定します ( |
|
|
|
Apache Camel 2.0: 再配信の試行に対するログレベルを指定します ( |
|
|
| 競合の回避を有効にします。これにより、一定のランダム化をバックオフのタイミングに追加して競合の可能性を低減します。 |
|
|
|
Apache Camel 2.0: この機能が有効な場合、デッドレターチャネルに送信されたメッセージは、ルートの開始時に存在した ( |
|
|
| 指数バックオフを有効にします。 |
再配信ヘッダー リンクのコピーリンクがクリップボードにコピーされました!
Apache Camel がメッセージの再配信を試みると、表6.2「デッドレター再配信ヘッダー」 に記載されているヘッダーを In メッセージに自動設定します。
| ヘッダー名 | 型 | 説明 |
|---|---|---|
|
|
|
Apache Camel 2.0: 配信に失敗した回数を返します。この値は、 |
|
|
|
Apache Camel 2.0: 再配信が 1 回以上試行された場合は true です。この値は |
|
|
|
Apache Camel 2.6: 再配信の最大設定を保持します ( |
再配信エクスチェンジプロパティー リンクのコピーリンクがクリップボードにコピーされました!
Apache Camel がメッセージの再配信を試みると、表6.3「再配信エクスチェンジプロパティー」 に記載されているエクスチェンジプロパティーを自動設定します。
| エクスチェンジプロパティー名 | 型 | 説明 |
|---|---|---|
|
|
|
失敗したルートのルート ID を提供します。このプロパティーのリテラル名は |
元のメッセージの使用 リンクのコピーリンクがクリップボードにコピーされました!
Apache Camel 2.0 で利用可能: エクスチェンジオブジェクトはルートを通過する際に変更される可能性があります。そのため、例外が発生したときに現行であるエクスチェンジがデッドレターチャネルの保存に適したコピーであるとは限りません。多くの場合、ルートによる変換の対象となる前に、ルート開始時に到達したメッセージをログに記録することが推奨されます。たとえば、以下のルートを見てみましょう。
from("jms:queue:order:input")
.to("bean:validateOrder");
.to("bean:transformOrder")
.to("bean:handleOrder");
from("jms:queue:order:input")
.to("bean:validateOrder");
.to("bean:transformOrder")
.to("bean:handleOrder");
上記のルートは受信 JMS メッセージをリッスンした後、validateOrder、transformOrder、および handleOrder の Bean のシーケンスを使用してメッセージを処理します。ただし、エラーが発生した場合にメッセージがどの状態であるかは分かりません。transformOrder Bean の前または後にエラーが発生しましたか ?以下のように useOriginalMessage オプションを有効にすると、jms:queue:order:input からの元のメッセージのログを確実に Dead Letter Channel に記録することができます。
// will use original body
errorHandler(deadLetterChannel("jms:queue:dead")
.useOriginalMessage().maximumRedeliveries(5).redeliveryDelay(5000);
// will use original body
errorHandler(deadLetterChannel("jms:queue:dead")
.useOriginalMessage().maximumRedeliveries(5).redeliveryDelay(5000);
Redeliver Delay パターン リンクのコピーリンクがクリップボードにコピーされました!
Apache Camel 2.0 で利用可能: delayPattern オプションは、再配信回数の特定範囲に遅延を指定するために使用されます。遅延パターンの構文: limit1:delay1;limit2:delay2;limit3:delay3;…。各 delayN は範囲 limitN ⇐ redeliveryCount < limitN+1 で再配信するように適用されます
たとえば、パターン 5:1000;10:5000;20:20000 を考えてみましょう。このパターンでは、3 つのグループが定義され、以下の再配信の遅延が発生します。
- 1 から 4 の試行 = 0 ミリ秒 (最初のグループは 5 で始まるため)。
- 5 から 9 の試行 = 1000 ミリ秒 (最初のグループ)。
- 10 から 19 の試行 = 5000 ミリ秒 (2 番目のグループ)。
- 20 以上の試行 = 20000 ミリ秒 (最後のグループ)。
制限 1 を加えてグループを開始し、開始遅延を定義できます。たとえば、1:1000;5:5000 では以下の再配信の遅延が発生します。
- 1 から 4 の試行 = 1000 ミリ (最初のグループ)。
- 5 以上の試行 = 5000 ミリ (最後のグループ)。
次の遅延を前の遅延よりも長くする必要はありません。あらゆる遅延値を使用できます。たとえば、Delay パターン 1:5000;3:1000 は 5 秒の遅延で始まり、遅延を 1 秒に減らします。
失敗したエンドポイント リンクのコピーリンクがクリップボードにコピーされました!
Apache Camel ルートメッセージ時に、エクスチェンジが送信された 最後 のエンドポイントが含まれるエクスチェンジプロパティーを更新します。したがって、以下のコードを使用して、現在のエクスチェンジが最後に送信された宛先の URI を取得できます。
// Java String lastEndpointUri = exchange.getProperty(Exchange.TO_ENDPOINT, String.class);
// Java
String lastEndpointUri = exchange.getProperty(Exchange.TO_ENDPOINT, String.class);
Exchange.TO_ENDPOINT は CamelToEndpoint と同等の文字列の定数になります。このプロパティーは、Camel がメッセージを 任意 のエンドポイントに送信するたびに更新されます。
ルーティング中にエラーが発生し、エクスチェンジがデッドレターキューに移動された場合、Apache Camel は CamelFailureEndpoint という名前のプロパティーを追加で設定します。これは、エラーが発生する前にエクスチェンジが最後に送信された宛先を特定します。したがって、以下のコードを使用すると、デッドレターキュー内から失敗したエンドポイントにアクセスできます。
// Java String failedEndpointUri = exchange.getProperty(Exchange.FAILURE_ENDPOINT, String.class);
// Java
String failedEndpointUri = exchange.getProperty(Exchange.FAILURE_ENDPOINT, String.class);
Exchange.FAILURE_ENDPOINT は、CamelFailureEndpoint と同等の文字列定数です。
これらのプロパティーは、指定の宛先エンドポイントの処理が完了した 後 に障害が発生した場合でも、現在のエクスチェンジで設定された状態を維持します。たとえば、以下のルートを見てみましょう。
from("activemq:queue:foo")
.to("http://someserver/somepath")
.beanRef("foo");
from("activemq:queue:foo")
.to("http://someserver/somepath")
.beanRef("foo");
foo Bean で障害が発生したと仮定します。この場合、Exchange.TO_ENDPOINT プロパティーと Exchange.FAILURE_ENDPOINT プロパティーに値が含まれ続けます。
onRedelivery プロセッサー リンクのコピーリンクがクリップボードにコピーされました!
Dead Letter Channel が再配信を実行する場合、再配信を試みる 直前 に実行される Processor を設定できます。これは、メッセージを再配信する前に変更する必要がある場合に使用できます。
たとえば、以下の Dead Letter Channel は、エクスチェンジの再配信前に MyRedeliverProcessor を呼び出すように設定されます。
ここで MyRedeliveryProcessor プロセスは以下のように実装されます。
シャットダウンまたは停止中の再配信の制御 リンクのコピーリンクがクリップボードにコピーされました!
ルートを停止したり、正常なシャットダウンを開始する場合、再配信の試行を継続するのがエラー処理のデフォルトの挙動になります。通常、これは望ましい動作ではないため、以下の例のように、allowRedeliveryWhileStopping オプションを false に設定すると、シャットダウンまたは停止中に再配信を無効にすることができます。
errorHandler(deadLetterChannel("jms:queue:dead")
.allowRedeliveryWhileStopping(false)
.maximumRedeliveries(20)
.redeliveryDelay(1000)
.retryAttemptedLogLevel(LoggingLevel.INFO));
errorHandler(deadLetterChannel("jms:queue:dead")
.allowRedeliveryWhileStopping(false)
.maximumRedeliveries(20)
.redeliveryDelay(1000)
.retryAttemptedLogLevel(LoggingLevel.INFO));
後方互換性の理由から、allowRedeliveryWhileStopping オプションはデフォルトで true になります。ただし、強行なシャットダウン中は、このオプションの設定に関係なく、再配信が常に抑制されます (たとえば、正常なシャットダウンがタイムアウトした場合など)。
onExceptionOccurred プロセッサーの使用 リンクのコピーリンクがクリップボードにコピーされました!
Dead Letter Channel は、例外発生後にメッセージのカスタム処理を可能にする onExceptionOccurred プロセッサーをサポートします。これは、カスタムロギングにも使用できます。onExceptionOccurred プロセッサーから出力される新しい例外は WARN としてログに記録され、無視されます。既存の例外を上書きすることはありません。
onRedelivery プロセッサーと onExceptionOccurred プロセッサーの違いは、onRedelivery プロセッサーは再配信の試行直前に処理できることです。ただし、例外の発生直後には処理できません。たとえば、再配信を試行する間隔で 5 秒の遅延が発生するようにエラーハンドラーを設定すると、再配信プロセスは例外発生から 5 秒後に呼び出されます。
以下の例は、例外発生時にカスタムロギングを実行する方法を示しています。onExceptionOccurred がカスタムプロセッサーを使用するように設定する必要があります。
errorHandler(defaultErrorHandler().maximumRedeliveries(3).redeliveryDelay(5000).onExceptionOccurred(myProcessor));
errorHandler(defaultErrorHandler().maximumRedeliveries(3).redeliveryDelay(5000).onExceptionOccurred(myProcessor));
onException 句 リンクのコピーリンクがクリップボードにコピーされました!
ルートビルダーで errorHandler() インターセプターを使用する代わりに、さまざまな例外タイプに異なる再配信ポリシーとデッドレターチャネルを定義する、一連の onException() 句を定義できます。たとえば、NullPointerException、IOException、Exception タイプごとに異なる動作を定義するには、Java DSL を使用してルートビルダーに以下のルールを定義できます。
再配信オプションは、再配信ポリシーメソッドをチェーンして指定されます (表6.1「再配信ポリシーの設定」 のように)。また、to() DSL コマンドを使用して Dead Letter Channel のエンドポイントを指定します。onException() 句で他の Java DSL コマンドを呼び出すこともできます。たとえば、前述の例は setHeader() を呼び出して、messageInfo という名前のメッセージヘッダーにエラーの情報を記録します。
この例では、NullPointerException および IOException 例外タイプが特別に設定されています。その他のすべての例外タイプは、汎用 Exception 例外インターセプターによって処理されます。デフォルトでは、Apache Camel は出力された例外に最も一致する例外インターセプターを適用します。完全に一致するものが見つからない場合は、最も近いベースタイプなどとの一致を試みます。最後に、他のインターセプターと一致しない場合、その Exception タイプのインターセプターは残りの例外すべてと一致します。
OnPrepareFailure リンクのコピーリンクがクリップボードにコピーされました!
デッドレターキューにエクスチェンジを渡す前に、onPrepare オプションを使用してカスタムプロセッサーがエクスチェンジを準備できるようにすることができます。これにより、エクスチェンジ失敗の原因など、エクスチェンジに関する情報を追加できます。たとえば、以下のプロセッサーは例外メッセージが含まれるヘッダーを追加します。
以下のように、プロセッサーを使用するようにエラーハンドラーを設定できます。
errorHandler(deadLetterChannel("jms:dead").onPrepareFailure(new MyPrepareProcessor()));
errorHandler(deadLetterChannel("jms:dead").onPrepareFailure(new MyPrepareProcessor()));
ただし、onPrepare オプションは、デフォルトのエラーハンドラーを使用して使用することもできます。
<bean id="myPrepare" class="org.apache.camel.processor.DeadLetterChannelOnPrepareTest.MyPrepareProcessor"/> <errorHandler id="dlc" type="DeadLetterChannel" deadLetterUri="jms:dead" onPrepareFailureRef="myPrepare"/>
<bean id="myPrepare"
class="org.apache.camel.processor.DeadLetterChannelOnPrepareTest.MyPrepareProcessor"/>
<errorHandler id="dlc" type="DeadLetterChannel" deadLetterUri="jms:dead" onPrepareFailureRef="myPrepare"/>