RocketMQ消息发送常见错误与解决方案

无法找到路由信息,其完整的错误堆栈信息如下:

在这里插入图片描述而且很多读者朋友会说Broker端开启了自动创建主题也会出现上述问题。

RocketMQ的路由寻找流程如下图所示:

在这里插入图片描述上面的核心关键点如下:

  • 如果Broker开启了自动创建Topic,在启动的时候会默认创建主题:TBW102,并会随着Broker发送到Nameserver的心跳包汇报给Nameserver,继而从Nameserver查询路由信息时能返回路由信息。

  • 消息发送者在消息发送时首先会查本地缓存,如果本地缓存中存在,直接返回路由信息。

  • 如果缓存不存在,则向Nameserver查询路由信息,如果Nameserver存在该路由信息,就直接返回。

  • 如果Nameserver不存在该topic的路由信息,如果没有开启自动创建主题,则抛出 No route info of this topic。

  • 如果开启了自动创建主题,则使用默认主题向Nameserver查询路由信息,并使用默认Topic的路由信息为自己的路由信息,将不会抛出 No route info of this topic。

通常情况下 No route info of this topic 这个错误一般是在刚搭建RocketMQ,刚入门 RocketMQ遇到的比较多,通常的排查思路如下:

  • 可以通过rocketmq-console查询路由信息是否存在,或使用如下命令查询路由信息:

cd ${ROCKETMQ_HOME}/bin

sh ./mqadmin topicRoute -n 127.0.0.1:9876 -t dw_test_0003

其输出结果如下所示:

在这里插入图片描述

  • 如果通过命令无法查询到路由信息,则查看Broker是否开启了自动创建topic,参数为:autoCreateTopicEnable,该参数默认为true。但在生产环境不建议开启。

  • 如果开启了自动创建路由信息,但还是抛出这个错误,这个时候请检查客户端(Producer)连接的Nameserver地址是否与Broker中配置的nameserver地址是否一致。

经过上面的步骤,基本就能解决该错误。

2、消息发送超时


消息发送超时,通常客户端的日志如下:

在这里插入图片描述

客户端报消息发送超时,通常第一怀疑的对象是RocketMQ服务器,是不是Broker性能出现了抖动,无法抗住当前的量。

那我们如何来排查RocketMQ当前是否有性能瓶颈呢?

首先我们执行如下命令查看RocketMQ 消息写入的耗时分布情况:

cd /${USER.HOME}/logs/rocketmqlogs/

grep -n ‘PAGECACHERT’ store.log | more

输出结果如下所示:

在这里插入图片描述

RocketMQ会每一分钟打印前一分钟内消息发送的耗时情况分布,我们从这里就能窥探RocketMQ消息写入是否存在明细的性能瓶颈,其区间如下:

  • [<=0ms] 小于0ms,即微妙级别的。

  • [0~10ms] 小于10ms的个数。

  • [10~50ms] 大于10ms小

  • 于50ms的个数

其他区间显示,绝大多数会落在微妙级别完成,按照笔者的经验如果100-200ms及以上的区间超过20个后,说明Broker确实存在一定的瓶颈,如果只是少数几个,说明这个是内存或pagecache的抖动,问题不大。

通常情况下超时通常与Broker端的处理能力关系不大,还有另外一个佐证,在RocketMQ broker中还存在快速失败机制,即当Broker收到客户端的请求后会将消息先放入队列,然后顺序执行,如果一条消息队列中等待超过200ms就会启动快速失败,向客户端返回[TIMEOUT_CLEAN_QUEUE]broker busy,这个在本文的第3部分会详细介绍。

在RocketMQ客户端遇到网络超时,通常可以考虑一些应用本身的垃圾回收,是否由于GC的停顿时间导致的消息发送超时,这个我在测试环境进行压力测试时遇到过,但生产环境暂时没有遇到过,大家稍微留意一下。

在RocketMQ中通常遇到网络超时,通常与网络的抖动有关系,但由于我对网络不是特别擅长,故暂时无法找到直接证据,但能找到一些间接证据,例如在一个应用中同时连接了kafka、RocketMQ集群,发现在出现超时的同一时间发现连接到RocketMQ集群内所有Broker,连接到kafka集群都出现了超时。

但出现网络超时,我们总得解决,那有什么解决方案吗?

我们对消息中间件的最低期望就是高并发低延迟,从上面的消息发送耗时分布情况也可以看出RocketMQ确实符合我们的期望,绝大部分请求都是在微妙级别内,故我给出的方案时,减少消息发送的超时时间,增加重试次数,并增加快速失败的最大等待时长。具体措施如下:

  • 增加Broker端快速失败的时长,建议为1000,在broker的配置文件中增加如下配置:

maxWaitTimeMillsInQueue=1000

主要原因是在当前的RocketMQ版本中,快速失败导致的错误为SYSTEM_BUSY,并不会触发重试,适当增大该值,尽可能避免触发该机制,详情可以参考本文第3部分内容,会重点介绍system_busy、broker_busy。

  • 如果RocketMQ的客户端版本为4.3.0以下版本(不含4.3.0)

将超时时间设置消息发送的超时时间为500ms,并将重试次数设置为6次(这个可以适当进行调整,尽量大于3),其背后的哲学是尽快超时,并进行重试,因为发现局域网内的网络抖动是瞬时的,下次重试的是就能恢复,并且RocketMQ有故障规避机制,重试的时候会尽量选择不同的Broker,相关的代码如下:

DefaultMQProducer producer = new DefaultMQProducer(“dw_test_producer_group”);

producer.setNamesrvAddr(“127.0.0.1:9876”);

producer.setRetryTimesWhenSendFailed(5);// 同步发送模式:重试次数

producer.setRetryTimesWhenSendAsyncFailed(5);// 异步发送模式:重试次数

producer.start();

producer.send(msg,500);//消息发送超时时间

  • 如果RocketMQ的客户端版本为4.3.0及以上版本

如果客户端版本为4.3.0及其以上版本,由于其设置的消息发送超时时间为所有重试的总的超时时间,故不能直接通过设置RocketMQ的发送API的超时时间,而是需要对其API进行包装,重试需要在外层收到进行,例如示例代码如下:

public static SendResult send(DefaultMQProducer producer, Message msg, int

retryCount) {

Throwable e = null;

for(int i =0; i < retryCount; i ++ ) {

try {

return producer.send(msg,500); //设置超时时间,为500ms,内部有重试机制

} catch (Throwable e2) {

e = e2;

}

}

throw new RuntimeException(“消息发送异常”,e);

}

3、System busy、Broker busy


在使用RocketMQ中,如果RocketMQ集群达到1W/tps的压力负载水平,System busy、Broker busy就会是大家经常会遇到的问题。例如如下图所示的异常栈。

在这里插入图片描述纵观RocketMQ与system busy、broker busy相关的错误关键字,总共包含如下5个:

  • [REJECTREQUEST]system busy

  • too many requests and system thread pool busy

  • [PC_SYNCHRONIZED]broker busy

  • [PCBUSY_CLEAN_QUEUE]broker busy

  • [TIMEOUT_CLEAN_QUEUE]broker busy

3.1 原理分析

我们先用一张图来阐述一下在消息发送的全生命周期中分别在什么时候会抛出上述错误。

在这里插入图片描述

根据上述5类错误日志,其触发的原有可以归纳为如下3种。

  • pagecache压力较大

其中如下三类错误属于此种情况

  • [REJECTREQUEST]system busy

  • [PC_SYNCHRONIZED]broker busy

  • [PCBUSY_CLEAN_QUEUE]broker busy
    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典

  • Java核心知识整理

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

Java核心知识

  • Spring全家桶(实战系列)

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

  • 其他电子书资料

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

以下是我私藏的面试题库:

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
59)]

Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

以下是我私藏的面试题库:

[外链图片转存中…(img-yV1xJoZh-1713282716860)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值