最近我们遇到了重试机制无法处理"低级别"错误。 由于我们的应用错误,我们尝试发送的消息大于rabbitmq的frame_max大小(默认配置)。问题是相同的消息导致消费者一次又一次地重新启动,并且重试机制(最多尝试3次)不起作用,因为它可能位于更高层(消费者弹簧级别的重试模板)而不是协议(与rabbitmq连接线程)。
是否有办法计算低级故障并在某个时刻停止尝试处理此类消息(即最大重试次数)?我在这里错过了什么吗?重试模板是简单的3次重试,其间有一些延迟。 我正在寻找一个强大的"处理此类失败的方法。 提前谢谢
重试配置:
@Bean
public RetryOperationsInterceptor workMessagesRetryInterceptor() {
return RetryInterceptorBuilder.stateless().retryOperations(retryTemplate(properties.getRetryMaxAttempts()))
.recoverer(workerMessageRecoverer())
.build();
}
private RetryTemplate retryTemplate(int maxRetries) {
RetryTemplate retryTemplate = new RetryTemplate();
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(properties.getRetryInitialInterval());
backOffPolicy.setMultiplier(properties.getRetryMultiplier());
backOffPolicy.setMaxInterval(properties.getRetryMaxInterval());
retryTemplate.setBackOffPolicy(backOffPolicy);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(maxRetries);
retryTemplate.setRetryPolicy(retryPolicy);
retryTemplate.registerListener(new LogOnRetryListener());
return retryTemplate;
}
@Bean
public SimpleMessageListenerContainer messageListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setRabbitAdmin(amqpAdmin());
container.setConnectionFactory(connectionFactory());
container.setQueueNames(properties.getQueueName());
container.setConcurrentConsumers(concurrentConsumers);
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
container.setAdviceChain(workMessagesAdviceChain()); // for retry logic
}
private Advice[] workMessagesAdviceChain() {
return new Advice[] {workMessagesRetryInterceptor()};
}
完整的堆栈跟踪
2014-11-16 22:29:24,800 [Rabbitmq Connection thread 527] ction.CachingConnectionFactory ERROR> Channel shutdown: connection error; protocol method: #method<connection.close>(reply-code=501, reply-text=FRAME_ERROR - type 2, all octets = <<>>: {frame_too_large,183845,131064}, class-id=0, method-id=0)
2014-11-16 22:29:24,852 [xxx.worker.queue3] SimpleMessageListenerContainer WARN > Consumer raised exception, processing can restart if the connection factory supports itcom.rabbitmq.client.ShutdownSignalException: connection error; protocol method: #method<connection.close>(reply-code=501, reply-text=FRAME_ERROR - type 2, all octets = <<>>: {frame_too_large,183845,131064}, class-id=0, method-id=0)
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.checkShutdown(BlockingQueueConsumer.java:245)
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:298)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:945)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:934)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$600(SimpleMessageListenerContainer.java:78)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1045)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
2014-11-16 22:29:24,853 [xxx.worker.queue3] SimpleMessageListenerContainer INFO > Restarting Consumer: tags=[[amq.ctag-rTulxrbOI4-tOvFr5w9QgQ]], channel=Cached Rabbit Channel: AMQChannel(amqp://xxx@ip:5672/,1), acknowledgeMode=AUTO local queue size=0
2014-11-16 22:29:24,871 [xxx.worker.queue3] WorkerQueueMessageListenerImpl INFO > Handling WorkMessage[81fd79bedd1d4bea9c2840e33dc31403, SubnetEventAnalysis]
2014-11-16 22:29:25,424 [control.xxx.worker.queue1] SimpleMessageListenerContainer WARN > Consumer raised exception, processing can restart if the connection factory supports itcom.rabbitmq.client.ShutdownSignalException: connection error; protocol method: #method<connection.close>(reply-code=501, reply-text=FRAME_ERROR - type 2, all octets = <<>>: {frame_too_large,183845,131064}, class-id=0, method-id=0)
at com.rabbitmq.client.impl.AMQConnection.startShutdown(AMQConnection.java:715)
at com.rabbitmq.client.impl.AMQConnection.shutdown(AMQConnection.java:705)
at com.rabbitmq.client.impl.AMQConnection.handleConnectionClose(AMQConnection.java:660)
at com.rabbitmq.client.impl.AMQConnection.processControlCommand(AMQConnection.java:615)
at com.rabbitmq.client.impl.AMQConnection$1.processAsync(AMQConnection.java:107)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:144)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:91)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:540)
at java.lang.Thread.run(Thread.java:662)
2014-11-16 22:29:25,425 [control.xxx.worker.queue1] SimpleMessageListenerContainer INFO > Restarting Consumer: tags=[[amq.ctag-EOnuPRZyGpbpdnxKumXpMA]], channel=Cached Rabbit Channel: AMQChannel(amqp://xxx@ip:5672/,1), acknowledgeMode=AUTO local queue size=0