例外処理
RabbitMQ Java クライアントを使用した多くの操作で、チェック済み例外がスローされる可能性があります。例: IOException
インスタンスがスローされるケースが多数あります。RabbitTemplate
、SimpleMessageListenerContainer
、その他の Spring AMQP コンポーネントは、これらの例外をキャッチし、AmqpException
階層内の例外の 1 つに変換します。これらは "org.springframework.amqp" パッケージで定義されており、AmqpException
は階層のベースです。
リスナーが例外をスローすると、ListenerExecutionFailedException
にラップされます。通常、メッセージはブローカーによって拒否され、再度キューに入れられます。defaultRequeueRejected
を false
に設定すると、メッセージが破棄されます (またはデッドレター交換にルーティングされます)。メッセージリスナーと非同期ケースに従って、リスナーは AmqpRejectAndDontRequeueException
(または ImmediateRequeueAmqpException
) をスローして、この動作を条件付きで制御できます。
ただし、リスナーが動作を制御できないエラーのクラスがあります。変換できないメッセージ (無効な content_encoding
ヘッダーなど) が発生した場合、メッセージがユーザーコードに到達する前にいくつかの例外がスローされます。defaultRequeueRejected
を true
(デフォルト) に設定すると (または ImmediateRequeueAmqpException
をスローすると)、このようなメッセージは何度も再配信されます。バージョン 1.3.2 より前では、この状況を回避するために、ユーザーは例外処理に従ってカスタム ErrorHandler
を作成する必要がありました。
バージョン 1.3.2 以降、デフォルトの ErrorHandler
は、回復不能なエラーで失敗したメッセージを拒否する (そして再キューイングしない) ConditionalRejectingErrorHandler
になりました。具体的には、次のエラーで失敗するメッセージを拒否します。
o.s.amqp…MessageConversionException
:MessageConverter
を使用して受信メッセージのペイロードを変換するときにスローされる可能性があります。o.s.messaging…MessageConversionException
:@RabbitListener
メソッドへのマッピング時に追加の変換が必要な場合、変換サービスによってスローされる可能性があります。o.s.messaging…MethodArgumentNotValidException
: リスナーで検証 (@Valid
など) が使用され、検証が失敗した場合にスローされる可能性があります。o.s.messaging…MethodArgumentTypeMismatchException
: 受信メッセージがターゲットメソッドに対して正しくない型に変換された場合にスローされる可能性があります。例: パラメーターはMessage<Foo>
として宣言されていますが、Message<Bar>
が受信されます。java.lang.NoSuchMethodException
: バージョン 1.6.3 で追加されました。java.lang.ClassCastException
: バージョン 1.6.3 で追加されました。
このエラーハンドラーのインスタンスを FatalExceptionStrategy
で構成して、ユーザーが条件付きメッセージ拒否の独自のルールを提供できるようにすることができます。たとえば、Spring Retry ( メッセージリスナーと非同期ケース ) から BinaryExceptionClassifier
へのデリゲート実装などです。さらに、ListenerExecutionFailedException
には、決定に使用できる failedMessage
プロパティが追加されました。FatalExceptionStrategy.isFatal()
メソッドが true
を返す場合、エラーハンドラーは AmqpRejectAndDontRequeueException
をスローします。デフォルトの FatalExceptionStrategy
は、例外が致命的であると判断された場合に警告メッセージをログに記録します。
バージョン 1.6.3 以降、ユーザー例外を致命的なリストに追加する便利な方法は、ConditionalRejectingErrorHandler.DefaultExceptionStrategy
をサブクラス化し、isUserCauseFatal(Throwable cause)
メソッドをオーバーライドして、致命的な例外に対して true
を返すことです。
DLQ メッセージを処理するための一般的なパターンは、これらのメッセージに time-to-live
を設定し、追加の DLQ 構成を設定して、これらのメッセージが期限切れになり、再試行のためにメインキューに戻されるようにすることです。この手法の問題は、致命的な例外を引き起こすメッセージが永久にループすることです。バージョン 2.1 以降、ConditionalRejectingErrorHandler
は、致命的な例外がスローされる原因となるメッセージの x-death
ヘッダーを検出します。メッセージはログに記録され、破棄されます。ConditionalRejectingErrorHandler
の discardFatalsWithXDeath
プロパティを false
に設定することで、以前の動作に戻すことができます。
バージョン 2.1.9 以降、これらの致命的な例外を含むメッセージは拒否され、コンテナーの確認モードが MANUAL であっても、デフォルトで再キューイングされません。これらの例外は通常、リスナーが呼び出される前に発生するため、リスナーはメッセージを確認または拒否する機会がなく、未確認の状態でキューに残ります。以前の動作に戻すには、ConditionalRejectingErrorHandler の rejectManual プロパティを false に設定します。 |