在消息传递过程中,可能遇到各种问题,如网络故障,服务不可用,资源不足等,这些问题可能导致消息处理失败,为了解决这些问题,RabbitMQ提供了重试机制,循序消息处理失败后重新发送.
1.1重试配置
retry:enabled: true # 开启消费者失败重试initial-interval: 5000ms # 初始失败等待时⻓为 5 秒max-attempts: 5 # 最⼤重试次数 ( 包括⾃⾝消费的一次)
1.2手动确认和自动确认下重试的区别
自动确认模式下,RabbitMQ会在消息被投递给消费者后自动确认消息,如果消费者处理消息时抛出异常,RabbitMQ根据配置的重试参数自动将消息重新入队,从而实现重试,重试次数和重试间隔等参数可以在RabbitMQ的配置中设定。
但是手动确认模式下,消费者需要显式地对消息进行确认,如果消费者在处理消息时遇到异常,可以选择不确认消息使消息可以重新入队,重试的控制权在于应用程序本身,而不是RabbitMQ的内部机制,应用程序可以通过自己的逻辑和利用RabbitMQ的高级特性来实现有效的重试策略。
1.3重试机制的注意事项
1.手动确认模式下:程序逻辑异常,多次重试消息依然处理失败,无法被确认,就一直是unacked状态,导致消息挤压.
2.自动确认模式下:程序逻辑异常,多次重试还是失败,消息就会被自动确认,那么消息就丢失了
2.TTL
TTL(time to live)就是过期时间,RabbitMQ可以对消息和队列设置TTL
当消息达到存货时间之后,还没有被消费,就会被自动清除
比如我们在网上购物,一定时间内没有付款,订单就会被自动取消
2.1设置消息的TTL
目前有两种方法设置消息的TTL.
一种时设置队列的TTL,队列中所有消息都有相同的过期时间.二是对消息本身进行单独设置,每条消息都TTL都可以不同,如果两种方法一起用,则消息的TTL以两者之间较小的那个数值为准.
先说明对每条消息设置TTL.可在发送消息的方法中加入expiration的属性参数,单位为毫秒.
messagePostProcessor.getMessageProperties().setExpiration(ttlTime);
2.2设置队列的TTL
设置队列的TTL方法就是在创建队列时加入x-message-ttl参数实现的,单位时毫秒.
@Bean("ttlQueue2")
public Queue ttlQueue2() {
//设置20秒过期
return QueueBuilder.durable(Constant.TTL_QUEUE2).ttl(20*1000).build();
}
2.3两者的区别
设置队列TTL属性的方法,一旦消息过期就会立马从队列中删除.
设置消息TTL的方法,即使消息过期,也不会马上从队列中删除,而是在即将投递到消费者之前进行判定的.
为什么会这样呢?
因为设置队列过期时间,队列中已过期的消息肯定在队列头部,RabbitMQ只要定期从对头开始扫描是否有过期消息即可.
而设置消息TTL的方式,每条消息的过期时间不同,如果要删除所有过期消息就需要扫描整个队列,所以不如等到此消息即将被消费时再判定是否过期,如果过期在进行删除即可.