微服务框架
【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】
服务异步通讯
50 消息可靠性
50.4 失败重试机制
50.4.2 消费者失败消息处理策略
在开启重试模式后,重试次数耗尽,如果消息依然失败,则需要有MessageRecoverer接口来处理,它包含三种不同的实现:
- RejectAndDontRequeueRecoverer:重试耗尽后,直接reject,丢弃消息。【默认】就是这种方式
- ImmediateRequeueMessageRecoverer:重试耗尽后,返回nack,消息重新入队
- RepublishMessageRecoverer:重试耗尽后,将失败消息投递到指定的交换机【相当于重发】
【举个栗子】
这就是一个普通的模型结构
现在生产者 发送了一条消息,经过交换机、队列到达了消费者,但是在消费者 处理的时候失败了 ,然后它就多次重试
直到 重试资源 耗尽
按照以前的方式,要么直接丢了,要么就是重新回到队列
RepublishMessageRecoverer 这种方案 会准备一个新的交换机
这个交换机专门用于接收失败消息,
重试资源耗尽后, 消费者就会将消息 投递给这个交换机,光有交换机不够,因为交换机只是用来转发消息,然后现在还得有 一个队列
这样投递到这个交换机的消息最终一定会进入 error.queue 这个队列中
然后就可以专门搞一个消费者 去监听这个error.queue 队列【兜底方案】
【如何实现?】
测试下RepublishMessageRecoverer处理模式:
- 首先,定义接收失败消息的交换机、队列及其绑定关系:
来一个新的配置类
package cn.itcast.mq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* ClassName: ErrorMessageConfig
* date: 2022/11/9 18:53
*
* @author DingJiaxiong
*/
@Configuration
public class ErrorMessageConfig {
// error 交换机
@Bean
public DirectExchange errorMessageExchange(){
return new DirectExchange("error.direct");
}
//队列
@Bean
public Queue errorQueue(){
return new Queue("error.queue");
}
//绑定
@Bean
public Binding errorMessageBinding(){
return BindingBuilder.bind(errorQueue()).to(errorMessageExchange()).with("error");
}
@Bean
public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate){
return new RepublishMessageRecoverer(rabbitTemplate,"error.direct","error");
}
}
- 然后,定义RepublishMessageRecoverer:
直接重启测试
OK, 重启完成
查看控制台
OK, 队列创建好了
交换机也创建好了, 关系也绑上 了
向simple.queue 发送一条消息
直接发送
查看IDEA 控制台日志
这次重试资源用完后,没有报错,说消息转发了
再次查看MQ 控制台
没毛病
而且,这条消息,不仅有,还把 异常的栈信息带过来了
牛逼!!!!!!!!
50.4.3 总结
如何确保RabbitMQ消息的可靠性?
- 开启生产者确认机制,确保生产者的消息能到达队列
- 开启持久化功能,确保消息未消费前在队列中不会丢失
- 开启消费者确认机制为auto,由spring确认消息处理成功后完成ack
- 开启消费者失败重试机制,并设置MessageRecoverer,多次重试失败后将消息投递到异常交换机,交由人工处理