问题描述
- 2020-11-10 15:58:08,客户成功给私有化公司美术宝导课,反馈没有导入成功,排查日志后生产者发送mq成功,消费者未收到消息,以为是qmq丢消息,继续观察(此时没有注意mq的消息体的大小,导课一次导入了30门课)
- 2020-11-11 10:06:41,客户成功反馈又导入了10门课,让我核对下是不是都导入成功的,经查询,消费者成功收到了消息,导课是成功的。纳闷为啥昨天丢消息了
- 2020-11-11 10:25:17,客户成功再次给私有化公司美术宝导课,让我核对下,总共导了42门课,发现没有导入成功,还是同一个原因,消费者没有收到消息。又复现了,应该不是qmq本身丢消息的问题,3次不可能丢2次,排查日志,结合客户成功导课的数量,猜测应该是消息过大导致的问题,先让客户成功,分批次导课,一次导入10门课,尝试。当天13:57-14:40,42门课分4次导入,成功,没有丢消息。业务正常,美术宝可以使用三节课提供的课程,可以使用学习功能。
- 2020-11-11 13:57-14:40,总共导课4次,均导课成功
问题定位
从表象看,已经很明显,就是一次导课的数量太多,一次mq的消息体太大,导致丢消息。学习支持私有化刚上线,为保证业务正常,让客户成功一次导课的数量控制下,控制在10门。
排查代码,代码中没有对消息过大做处理,代码如下:
1 | Message message = producer.generateMessage(CopyCourseToPrivatizationConst.SUBJECT_CONST); |
查询qmq官网已对这种情况做了说明
QMQ的Message.setProperty(key, value)如果value是字符串,则value的大小默认不能超过32K,如果你需要传输超大的字符串,请务必使用message.setLargeString(key, value),这样你甚至可以传输十几兆的内容了,但是消费消息的时候也需要使用message.getLargeString(key)。
查看qmq源码得到的结论一样:
本质还是消息体超过32k,生产者发送消息就失败了
问题修复
按提示当消息体大于32k(value长度大于8192),用message.setLargeString(key, value),消费者则使用message.getLargeString(key)获取,该修改在下一个迭代上线,不影响业务。
问题总结
在看其他项目中,用qmq的地方已经有对消息过大有做处理。其他同学应该遇到过这个坑。
qmq的Message.setProperty(key, value),如果value是字符串,则value的大小默认不能超过32K,如果你需要传输超大的字符串,请务必使用message.setLargeString(key, value),这样你甚至可以传输十几兆的内容了,但是消费消息
的时候也需要使用message.getLargeString(key)。