2015-02-06 5 views
3

AmqpException을 내 소비자에게 던지고 있습니다. 메시지는 FIFO 순서로 대기열로 다시 돌아오고 나중에 언젠가 재 처리 될 것으로 예상됩니다.amqp가있는 rabbitmq - AmqpException의 경우에 메시지가 표시되지 않습니다.

마치 봄 AMQP가 메시지를 대기열로 다시 보내지 않는 것처럼 보입니다. 대신 실패한 메시지를 반복해서 다시 처리하려고합니다. 새로 도착한 메시지가 처리되지 않습니다. 붙어있는 것들은 AMQP 콘솔 내부의 영원히 "풀린"상태로 나타납니다.

의견이 있으십니까?

답변

7

이것이 바로 rabbitmq/Spring AMQP의 작동 방식입니다. 메시지가 거부되면 (예외가 발생 함) 메시지는 기본적으로 다시 큐에 저장되고 큐의 헤드에 다시 넣어 지므로 즉시 재 시도됩니다.

... 언젠가는 미래에 재 처리됩니다.

상황을 적절하게 구성해야합니다.

먼저 메시지를 다시 대기열에 넣지 말라고 브로커에 알려야합니다. 이 작업은 수신기 컨테이너에 defaultRequeueRejected을 false로 설정하여 수행합니다 (기본적으로 true). 또는 AmqpRejectAndDontRequeueException을 던져 컨테이너가 개별 메시지를 거부 (및 재 요청하지 않음)하도록 지시 할 수 있습니다.

하지만 그 끝은 아닙니다. 그냥 그렇게하면 거부 된 메시지가 삭제됩니다.

대기열에 대해 Dead Letter Exchange/Queue을 설정해야합니다. 거부 된 메시지는 버려지지 않고 DLX/DLQ로 전송됩니다. 일반적으로 대기열 인수가 아닌 정책을 사용하는 것이 좋습니다.

마지막으로 DLQ에서 메시지 수명 시간을 설정할 수 있으므로 그 시간 이후에는 메시지가 대기열에서 제거됩니다. 대기열 (DLQ)에 다른 적절한 데드 - 레 교환을 설정하면, 시간이 만료 된 후에 메시지가 다시 원래 대기열로 다시 대기하게 할 수 있습니다.

원본 큐에서 거부 된 배달에만 작동합니다. 해당 큐에서 메시지가 만료되면 작동하지 않습니다.

자세한 내용은 this answer과 그 질문의 링크를 참조하십시오.

x-death 헤더의 내용을 사용하여 몇 가지 시도 후에 완전히 포기해야하는지 (예외를 잡아 내고 어떻게 든 잘못된 메시지를 처리하고 예외를 던지지 말고 컨테이너가 메시지).

+0

게리, 피드백에 감사드립니다. – Vladimir

+0

AmqpException을 던질 때 Spring AMQP RetryOperationsInterceptor를 사용하려고합니다. 최대 재시도 시도에 도달하면 "Recoverer"는 AmqpRejectAndDontRequeueException을 throw하여 메시지를 버립니다.재 시도 인터셉터 (지수 백 오프로 몇 시간이 걸릴 수 있음)에 의한 재시도 사이에 메시지가 대기열로 되돌아 가서 새로 도착한 메시지를 처리 ​​할 수있는 것으로 나타났습니다. – Vladimir

+0

아니요; 재시도 인터셉터는 스레드를 청취자에게 전달하기 전에 스레드를 차단합니다. 이것은 재시도 사이의 짧은 지연에만 적합합니다. 내가 재방송을 연기하기 위해 설명한대로 브로커를 사용해야합니다. 소비자가 재 전달하기 전에 잠시 기다려달라고 브로커에 알리는 다른 방법은 없습니다. 그것은 단지 amqp 프로토콜의 일부가 아닙니다. JMS를 사용하는 경우에도 이러한 지연은 브로커의 독점이며 jms API의 일부가 아닙니다. –