问题一:消息因为网络原因无法到达broker
TODO 解决方案 每发送一个消息都做好日志记录(给数据库保存每一个消息的详细信息) 定期扫描数据库 将失败的消息在发送一遍
问题二:消息到达broker,broker要将消息持久化到磁盘才算成功,此时broker尚未持久化成功就宕机
TODO 解决方案:实现product与broker之间的消息确认机制,修改数据库消息状态
问题三:自动ACK的状态下,消费者收到消息,但是还没来得及消费消息就宕机了
TODO 解决方案:一定要开启手动ACK,消息消费成功才发送ACK,将消息从队列中移除,失败或者没来得及处理就重新入队。
问题四:消息消费成功,事务已经提交,ack时,机器宕机。导致没有ack成功,Broker的消息 重新由unack变为ready,并发送给其他消费者。
TODO 解决方案:将消息消费逻辑设计为幂等性的,比如释放库存有工作单的标志标志。
问题五:
消息积压:由于消费者宕机积压 、消费者消费能力不足、 发送者发送流量太大
TODO 解决方案:
1、上线更多的消费者,进行正常消费
2、上线专门的队列消费服务,将消息先批量取出来,记录数据库,离线慢慢处理
对于问题2:
* 实现product与broker之间的消息确认机制(ConfirmCallback) 分两步
* 1、spring.rabbitmq.publisher-confirms=true
* 2、设置确认回调,就是下面这个方法
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
* @param correlationData 当前消息的唯一关联数据(这个是消息的唯一ID)
* @param b 消息是否成功收到
* @param s 失败的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
// broker收到了
System.out.println("confirm...correlationData["+correlationData+"]==>ack["+b+"]==>reason["+s+"]");
}
});
对于问题3:
* 实现交换机与队列之间的消息确认机制(ReturnCallback) 分两步
* 1、spring.rabbitmq.publisher-return=true
* 2、设置确认回调,就是下面这个方法
// 报错回调
// 消息抵达队列确认回调,只要消息没有投递给指定的队列,就触发这个失败回调
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
* @param message 投递失败的消息详细信息
* @param replyCode 回复的状态码
* @param replyText 回复的文本内容
* @param exchange 当时的消息发送给的那个交换机
* @param routingKey 当时这个消息用哪个路由键
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
// 报错了,修改数据库当前的消息状态-》错误
System.out.println("fail message["+message+"]==>replyCode["+replyCode+"]==>replyText["+replyText+"]==>exchange["+exchange+"]==>routingKey["+routingKey+"]");
}
});