记一次 XXL-MQ消息消费失败的排查过程

624 阅读3分钟

写在前面

     作者一直想深入的去研究一款消息队列MQ,例如 延迟消费,广播消息,失败重试等机制.
 奈何市面上的MQ中间件太多了,如kafka,activeMQ,rocketMQ....所以也一直在纠结该以哪款为入手点,对新人友好?
 想起作者曾深入的研究了xuxueli大佬的分布式调度系统(XXL-JOB),然后进入XXL社区,刚好发现了的另一个开源项目,即分布式消息队列(XXL-MQ).       
   
   简而言之四个字,以小见大,懂得都懂
    

问题复现

 生产者A成功发送了数条有效消息,并且消息中心有对应记录,但是消费者B一直消费失败,没有反应

wecom-temp-329951d87243229879b899b3a00450f3.png

wecom-temp-4c4eabe6442edf2a0164f291201d659d.png

企业微信截图_9c259b02-7b5a-47bb-9bd2-a11349205445.png

问题分析

 首先上一张简易图,来描述一个消息从生产到消费的过程
 1 生产者A推送消息至MQ消息中心
 2 MQ消息中心将此消息进行备份保存
 3 消费者B开启定时线程轮训获取MQ消息中心 消息com.xxl.mq.client.consumer.thread.ConsumerThread
 4 消息中心返回消息

wecom-temp-f59b5efe6ba083048241d079853fa04a.png

结合我们前面的图,消息发送成功,数据库也有对应数据,那就是 3,4 步有问题了,
我们Debug打下断点看下
// pullNewMessage // 向消息中心拉取消息
List<XxlMqMessage> messageList = XxlMqClientFactory.getXxlMqBroker().pullNewMessage(mqConsumer.topic(), mqConsumer.group(), activeInfo.rank, activeInfo.total, 100);

wecom-temp-a2596b47673846f0798a11753dbc90c2.png

List<XxlMqMessage> list = xxlMqMessageDao.pullNewMessage(XxlMqMessageStatus.NEW.name(), topic, group, consumerRank, consumerTotal, pagesize);

企业微信截图_9df4cf8e-ff6b-45b3-aaea-a9cb9f0655f5.png

这里我们就看到了这里的DAO层 没有查询出数据库的数据,导致没有拉到消息,
我们用mybatis-log插件来看一下这里的sql查询语句是什么
#MybatisLog插件配置 可用于查看mybatis 底层执行sql 过程,默认关闭,根据业务自行打开
mybatis.configuration.log-impl:org.apache.ibatis.logging.stdout.StdOutImpl

企业微信截图_cce94325-9df0-4cd0-9b28-551090b3b4a0.png

得到查询的sql语句
SELECT *
FROM xxl_mq_message t
WHERE t.topic = 'topic_1'
AND t.group = 'DEFAULT'
AND t.status = 'NEW'
AND t.effectTime < NOW()
AND ((t.shardingId = 0
		AND MOD(t.id, 2) = 0)
	OR (t.shardingId > 0
		AND MOD(t.shardingId, 2) = 0))
ORDER BY t.id ASC
LIMIT 100
 最后发现 执行select now() 本来是获取当前时间的,不应该是17:50:00 这样吗?
 为什么是 07:12:00 这样差这么大?

企业微信截图_f214bbb1-15bd-41b7-b3d0-c198621ee739.png

 然后登录我的Mysql(docker部署)服务器查看时间是否正确,是否有人在演我?
 果然如此 Mysql容器内居然时间是Tue Feb 22 07:56:10 UTC 2022
 和我的虚拟机 20220222日 星期二 15:54:45 CST 这种一看就是时间格式时区这些对不上
 也因此导致了查询语句 select now() 匹配的时候不对,然后没有查询出数据,消费者也就没有可消费的

企业微信截图_ea165b80-b837-45b4-bfea-1a2b3bb47191.png

问题解决

既然知道了是Mysql容器时区问题的那就直接暴力点,将mysql的时区修改统一就好,参照以下链接

docker mysql 修改时区

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 然后重启mysql

问题验证/完美解决

wecom-temp-b043b45fea19f2e7bee8da7d8418a5c8.png

写在后面

持续更新分布式消息队列XXL_MQ源码解读
以小见大,由浅入深,逐渐领略消息中间件背后的故事

我是杨少,祝你幸福