我目前正在使用带弹簧的RabbitMQ(spring-rabbit-1.2.0-RELEASE),配置如下:
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"/>
<!-- Asynchronous exchanges -->
<!-- Admin -->
<rabbit:admin connection-factory="connectionFactory"/>
<!-- Error Handler -->
<bean id="biErrorHandler" class="my.project.sync.BiErrorHandler" />
<!-- Message converter -->
<bean id="biMessageConverter" class="my.project.sync.BiMessageConverter"/>
<bean id="retryInterceptor" class="org.springframework.amqp.rabbit.config.StatefulRetryOperationsInterceptorFactoryBean">
<property name="messageRecoverer" ref="rejectAndDontRequeueRecoverer"/>
<property name="retryOperations" ref="retryTemplate" />
<property name="messageKeyGenerator" ref="biKeyGenerator" />
</bean>
<bean id="biKeyGenerator" class="my.project.sync.BiMessageKeyGenerator"/>
<bean id="rejectAndDontRequeueRecoverer" class="org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer"/>
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="3000" />
<property name="maxInterval" value="30000" />
</bean>
</property>
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="3" />
</bean>
</property>
</bean>
<rabbit:queue id="biSynchronizationQueue" name="BI_SYNCHRONIZATION_QUEUE" durable="true" />
<rabbit:listener-container message-converter="biMessageConverter" concurrency="1"
connection-factory="connectionFactory"
error-handler="biErrorHandler"
advice-chain="retryInterceptor"
acknowledge="auto">
<rabbit:listener queues="BI_SYNCHRONIZATION_QUEUE" ref="biSynchronizationService" method="handleMessage"/>
</rabbit:listener-container>
我想在第三次尝试后在队列的尾部重新排队消息。但我没有找到办法实现这一点。
有人有想法吗?
提前感谢您的帮助。
答案 0 :(得分:7)
不使用RejectAndDontRequeueRecoverer
,而是使用使用MessageRecoverer
的自定义RabbitTemplate
将邮件发送到队列的后面;然后抛出AmqpRejectAndDontRequeueException
,这样邮件就会被拒绝。
您可以继承RejectAndDontRequeueRecoverer
,在recover()
中发送消息,然后调用super.recover()
(只会抛出异常)。或者只是在您自己的recover()
。
答案 1 :(得分:3)
我使用了这个技巧,但是后来使用了一个死信队列。对我来说,它比将消息放在队列末尾更明确。
<rabbit:queue name="content.variantchange.queue" durable="true" queue-arguments="queueArguments"/>
<util:map id="queueArguments">
<entry key="x-dead-letter-exchange" value="content.deadletter.topic"/>
</util:map>
<rabbit:fanout-exchange name="content.deadletter.topic">
<rabbit:bindings>
<rabbit:binding queue="content.deadletter.queue"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
<rabbit:queue name="content.deadletter.queue" durable="true"/>
一旦你有了死信队列,你可以通过另一个消费者做任何你想做的事情(包括将它添加回原始队列。)
我最后还使用了无状态版本的拦截器Gary推荐,这让我不必担心消息ID生成器。
<bean id="retryInterceptor" class="org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterceptorFactoryBean">
<property name="messageRecoverer" ref="rejectAndDontRequeueRecoverer"/>
<property name="retryOperations" ref="retryTemplate" />
</bean>