英文:
Spring boot rabbitmq dead queue not stopping flow on exception
问题
I am learning Spring Boot (version 2.2.5.RELEASE) with RabbitMQ based on online resources. The issue I am facing is that when purposely throwing an exception, it should retry only 6 times. However, the message keeps retrying without stopping. Below is my application.yml configuration:
server:
servlet:
contextPath: /test
spring:
rabbitmq:
username: guest
password: guest
listener:
simple:
retry:
enabled: true
initial-interval: 3s
max-attempts: 6
max-interval: 10s
multiplier: 2
Here is the RabbitMQ configuration class:
@Configuration
public class RabbitMQConfig {
@Bean
TopicExchange deadLetterExchange() {
return new TopicExchange("deadLetterExchange");
}
// Other beans...
@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("javainuse.queue");
container.setMessageListener(listenerAdapter);
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(ReceiveMessageHandler receiver) {
return new MessageListenerAdapter(receiver, "handleMessage");
}
}
And here is the class that consumes the message:
@Component
@Slf4j
@RequiredArgsConstructor
public class ReceiveMessageHandler {
private final SendService sendService;
public void handleMessage(@Valid dto dto) {
String test = null;
// Purposely throw null pointer to test dead queue
test.toString();
sendService.sendSomething(dto);
}
}
Despite configuring max-attempts: 6
in the application.yml, the null pointer exception keeps retrying beyond 6 times. Could someone help me identify what I'm missing here, please?
英文:
I am learning spring boot (version 2.2.5.RELEASE) with RabbitMQ based on online resources:
The issue I am experiencing is that when I am throwing purposely an exception, it should retry only 6 times and after that the message should be moved to the dead queue but it is not the case as it keeps retrying without stopping.
Please find below my application.yml:
server:
servlet:
contextPath: /test
spring:
rabbitmq:
username: guest
password: guest
listener:
simple:
retry:
enabled: true
initial-interval: 3s
max-attempts: 6
max-interval: 10s
multiplier: 2
Please find below rabbitMQ configuration class:
@Configuration
public class RabbitMQConfig {
@Bean
TopicExchange deadLetterExchange() {
return new TopicExchange("deadLetterExchange");
}
@Bean
TopicExchange exchange() {
return new TopicExchange("javainuseExchange");
}
@Bean
Queue dlq() {
return QueueBuilder.durable("deadLetter.queue").build();
}
@Bean
Queue queue() {
return QueueBuilder.durable("javainuse.queue").withArgument("x-dead-letter-exchange", "deadLetterExchange")
.withArgument("x-dead-letter-routing-key", "deadLetter").build();
}
@Bean
Binding DLQbinding() {
return BindingBuilder.bind(dlq()).to(deadLetterExchange()).with("deadLetter");
}
@Bean
Binding binding() {
return BindingBuilder.bind(queue()).to(exchange()).with("javainuse");
}
@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("javainuse.queue");
container.setMessageListener(listenerAdapter);
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(ReceiveMessageHandler receiver) {
return new MessageListenerAdapter(receiver, "handleMessage");
}
}
Please find below my class that consume the message:
@Component
@Slf4j
@RequiredArgsConstructor
public class ReceiveMessageHandler {
private final SendService sendService;
public void handleMessage(@Valid dto dto) {
String test = null;
//purposely throw null pointer to test dead queue
test.toString();
sendService.sendSomething(dto);
}
When the null pointer exception is thrown it keeps retrying instead of stopping after 6 times max-attempts: 6
as per application.yml config.
Can anyone point me what I am missing here, please?
答案1
得分: 2
你正在创建自己的容器 bean,因此.yml
属性未被应用。使用RetryInterceptorBuilder.stateless()...
来构建重试建议并将其注入到监听器容器(建议链)中。
您还需要配置恢复器。
builder.recoverer(new RejectAndDontRequeueRecoverer());
这将在重试用尽时将队列指向死信队列(DLQ)。
请参阅Spring AMQP 文档。
英文:
You are creating your own container bean so the .yml properties are not being applied. Use a RetryInterceptorBuilder.stateless() ...
to build the retry advice and inject it into the listener container (advice chain).
You also need to configure the recoverer.
builder.recoverer(new RejectAndDontRequeueRecoverer());
Which will direct the queue to the DLQ when retries are exhausted.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论