前言
消费者在处理消息的过程中可能会发生异常,那么此时此刻该如何处理这个异常的消息呢?
RabbitMQ
有两个方法channel.basicNack
或 channel.basicReject
能够让消息重新回到原队列中,这样子可以实现重试。但是如果第二次消费又发生了异常,一直消费一直异常。由于没有明确重试次数,会造就无限重试,这是一个致命的问题。
本文就来使用spring-rabbit
中自带的retry
功能来解决这个问题。
编码
依赖
starter-amqp
中包含了spring-rabbit
。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>compile</scope>
</dependency>
配置
需要进行简单的配置即可开启
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: auto # 消息确认方式,其有三种配置方式,分别是none、manual(手动ack) 和auto(自动ack) 默认auto
retry:
enabled: true #监听重试是否可用
max-attempts: 5 #最大重试次数 默认为3
initial-interval: 2000 # 传递消息的时间间隔 默认1s
host: 47.105.*
port: 5672
virtual-host: /*-1
username: *
password: *
mq:
queueBinding:
queue: prod_queue_pay
exchange:
name: exchang_prod_pay
type: topic
key: prod_pay
创建业务队列、交换机
@Configuration
public class RabbitConfig {
@Value("${mq.queueBinding.queue}")
private String queueName;
@Value("${mq.queueBinding.exchange.name}")
private String exchangeName;
@Value("${mq.queueBinding.key}")
private String key;
/**
* 业务队列
* @return
*/
@Bean
public Queue payQueue(){
Map<String,Object> params = new HashMap<>();
return QueueBuilder.durable(queueName).withArguments(params).build();
}
@Bean
public TopicExchange payTopicExchange(){
return new TopicExchange(exchangeName,true,false);
}
//队列与交换机进行绑定
@Bean
public Binding BindingPayQueueAndPayTopicExchange(Queue payQueue, TopicExchange payTopicExchange){
return BindingBuilder.bind(payQueue).to(payTopicExchange).with(key);
}
}
生产者
@Component
@Slf4j
public class RabbitSender {
@Value("${mq.queueBinding.exchange.name}")
private String exchangeName;
@Value("${mq.queueBinding.key}")
private String key;
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg){