wordpress站点安装/怎么拿到百度推广的代理
问题描述:
rmq消息队列中接收到了消息,并由消费者消费,由于下游服务异常,导致异常抛出,消费者消费消息失败,导致消息一直处于unack,return给rmq-server,重新被消费,但消费失败多次后,不再给消费者(日志中后续没有再打印关于该消息的消费start日志,且始终无end日志),并且队列中没有该消息。
分析:
1、可能未做持久化
2、消费失败,导致不再重试,放入别的地方(maybe是rmq某种机制)
一、消息持久化(时机:内存紧张、消息中强制要求)
队列持久化、message持久化、exchange持久化
1.queue设置为durable=true
2.message的deliveryMode=2,这里的deliveryMode=1代表不持久化,deliveryMode= 2代表持久化。
3.另外,exchange也需要持久化,但是,如果不持久化,broker重启后,exchange将不存在,producer就无法正常发送消息,故exchange设置成持久化,同样,durable=true。
这才算持久化完成。
做了持久化配置,仍不能保证消息不会丢失。
首先,consumer角度看,若autoAck=true,接受消息后,没来得及处理就crash掉(此段未验证)
其次,消息的落盘需要有一个时间,一般是25毫秒,才能刷进去
落盘时机,一个一兆大小的buffer,满了,写入文件(不是磁盘),有一个timeout=25ms,不论buffer满不满,buffer和文件内容都会刷到磁盘。
so,25ms内,若消息来了,未到刷盘时机,会导致消息丢失。
这仅仅是持久化的办法。
若可靠的办法,就是设置集群,主从。以及消息确认机制(事务+confirm)
目前来看,我们的持久化均以配置,现象上看,已经发送了多次消息给消费者消费,故已经超过25ms落盘时间,丢失消息原因不太可能是消息未落盘。
二、重试机制 (重试次数达到后,不再被消费)
spring rmq的重试机制我们项目中并未配置,且通过测试,会无限次重试。
以上测试在项目版本和rmq版本均与测试环境一致前提下进行。
总结:
持久化未落盘及可能的Dead Letter Exchanges机制均验证,且kill进程等均未复现,后续继续观察。
另外,附上可能的情况:
msg进入rabbitmq-server后,根据是否是持久化消息,可能会有以下几种状态:
%% Definitions:
%% alpha:
消息本身和消息位置索引都只在内存中
%% beta:
消息本身存储在磁盘中,但是消息的位置索引存在内存中
%% gamma:
消息本身存储在磁盘中,但是消息的位置索引存在内存中和磁盘中
%% delta:
消息本身和消息的位置索引都值存储在磁盘中
消息队列内部有BQ(backing_queue)的概念,用来区分不同的消息,如下:
其中Q1、Q4只包含alpha状态的消息,Q2和Q3包含Beta和gamma状态的消息,Delta只包含delta状态的消息。
也就是,当msg是持久化的消息类型时,在rmq-server中,msg可能处于delta、gamma、beta的状态。
且在日志中,查找到warning rabbitmq rebuilding indices from scratch消息,源码中,该日志的打印说明如下:
%% if we found crashed compactions we trust neither the
%% file_summary nor the location index. Note the file_summary is
%% left empty here if it can't be recovered.
所以,对于持久化的消息,在机器重启时,若消息处于beta状态,那么内存中的消息索引将丢失,导致disk中的msg无法被找到,出现消息”丢失“。
参考资料:
博客:
https://blog.csdn.net/zhousenshan/article/details/78681968
https://www.cnblogs.com/163yun/p/9154332.html
https://www.jianshu.com/p/19e0927315da
https://blog.csdn.net/yeweiouyang/article/details/74943278
官方文档:
ttp://www.rabbitmq.com/persistence-conf.html
http://www.rabbitmq.com/dlx.html