Rabbitmq 尽管DefaultRequeueRejected=false,rabbit代理中的消息仍然未确认

Rabbitmq 尽管DefaultRequeueRejected=false,rabbit代理中的消息仍然未确认,rabbitmq,spring-integration,spring-amqp,Rabbitmq,Spring Integration,Spring Amqp,我的场景:我向我的兔子代理发布了两条消息,在处理第一条消息时发生了一个未经处理的异常 我的问题是:为什么消息在代理中保持未确认状态,因此为什么第二条消息没有被排队和处理 一些信息: 我正在使用SpringAMQP1.5.4和SpringIntegration4.2.4。请参阅下面的代码 我已设置死信交换,并且它正在按预期工作,即当我收到消息时,它将转发到DLX,并在那里过期。然后将其转发到主交换机 我想要的是: 我希望未处理的异常(即SimpleMessageListenerContainer捕

我的场景:我向我的兔子代理发布了两条消息,在处理第一条消息时发生了一个未经处理的异常

我的问题是:为什么消息在代理中保持未确认状态,因此为什么第二条消息没有被排队和处理

一些信息: 我正在使用SpringAMQP1.5.4和SpringIntegration4.2.4。请参阅下面的代码 我已设置死信交换,并且它正在按预期工作,即当我收到消息时,它将转发到DLX,并在那里过期。然后将其转发到主交换机

我想要的是: 我希望未处理的异常(即SimpleMessageListenerContainer捕获的异常)会导致amqp消息被Nack'd而不是保持未确认状态

我看到: 有3次重试尝试处理该消息,但由于我的强制异常而失败,请参阅下面的ErrorHandler中的代码

BlockingQueueConsumer的consumer标记是相同的,因此我猜BlockingQueueConsumer没有重新启动。但是,下面的日志显示它确实在继续等待消息

我想知道为什么BlockingQueueConsumer没有nack消息,为什么后续消息没有被消费,尽管日志中有证据表明消费者正在等待消息

欢迎提供任何建议或背景信息

@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory, Queue mainQueue, RetryOperationsInterceptor retryOperationsInterceptor) {
    SimpleMessageListenerContainer retVal = new SimpleMessageListenerContainer(connectionFactory);
    retVal.addQueues(mainQueue);
    retVal.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    retVal.setDefaultRequeueRejected(false);
    retVal.setAdviceChain(new Advice[]{retryOperationsInterceptor});
    return retVal;
}

@Bean
public RetryOperationsInterceptor retryOperationsInterceptor () {
    return stateless().recoverer(new RejectAndDontRequeueRecoverer()).build();
}

<int-amqp:inbound-channel-adapter
    channel="fromRabbitChannel"
    error-channel="errorChannel"
    listener-container="simpleMessageListenerContainer"
    />

<int:service-activator ref="errorHandler" input-channel="errorChannel" method="handleError"/>

@MessageEndpoint
public class ErrorHandler {
    public void handleError(Message<MessagingException> message) throws IOException {
        throw new IllegalStateException("FORCED EXCEPTION");
    }
}

09:49:38.219 [SimpleAsyncTaskExecutor-1] INFO  c.p.a.f.ErrorHandler - Throwing an exception!!
09:49:38.219 [SimpleAsyncTaskExecutor-1] DEBUG o.s.retry.support.RetryTemplate - Checking for rethrow: count=3
09:49:38.219 [SimpleAsyncTaskExecutor-1] DEBUG o.s.retry.support.RetryTemplate - Retry failed last attempt: count=3
09:49:38.220 [SimpleAsyncTaskExecutor-1] WARN  o.s.a.r.r.RejectAndDontRequeueRecoverer - Retries exhausted for message (Body:'[B@c78ef32(byte[97])'MessageProperties [blah blah])
    org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener threw exception
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.java:865) [spring-rabbit-1.5.2.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:760) [spring-rabbit-1.5.2.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:680) [spring-rabbit-1.5.2.RELEASE.jar:na]
....
....
09:49:38.221 [SimpleAsyncTaskExecutor-1] WARN  o.s.a.r.l.ConditionalRejectingErrorHandler - Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Retry Policy Exhausted
at org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer.recover(RejectAndDontRequeueRecoverer.java:44) ~[spring-rabbit-1.5.2.RELEASE.jar:na]
at org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterceptorFactoryBean$1.recover(StatelessRetryOperationsInterceptorFactoryBean.java:59) ~[spring-rabbit-1.5.2.RELEASE.jar:na]
at org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterceptorFactoryBean$1.recover(StatelessRetryOperationsInterceptorFactoryBean.java:53) ~[spring-rabbit-1.5.2.RELEASE.jar:na]
at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:124) ~[spring-retry-1.1.2.RELEASE.jar:na]
at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:458) ~[spring-retry-1.1.2.RELEASE.jar:na]
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:320) ~[spring-retry-1.1.2.RELEASE.jar:na]
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:168) ~[spring-retry-1.1.2.RELEASE.jar:na]
....
....
09:49:38.222 [SimpleAsyncTaskExecutor-1] DEBUG o.s.a.r.l.BlockingQueueConsumer - Retrieving delivery for Consumer: tags=[{amq.ctag-XVCBQNXxCMFERaF1kbeI3Q=debitCardStatusQueue}], channel=Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5671/,1), acknowledgeMode=MANUAL local queue size=0
09:49:39.222 [SimpleAsyncTaskExecutor-1] DEBUG o.s.a.r.l.BlockingQueueConsumer - Retrieving delivery for Consumer: tags=[{amq.ctag-XVCBQNXxCMFERaF1kbeI3Q=debitCardStatusQueue}], channel=Cached Rabbit Channel: AMQChannel(amqp://guest@127.0.0.1:5671/,1), acknowledgeMode=MANUAL local queue size=0
retVal.setAcknowledgeMode.MANUAL


对于手动确认,您负责确认或拒绝消息;如果将模式设置为自动,则容器将仅确认/确认;然后它将完全按照您的要求运行。

谢谢Gary。。。这就是我所需要做的一切。@Gary,你能帮我吗:我读了这篇文章,但SpringBoot似乎是我的另一种方法