共计 3522 个字符,预计需要花费 9 分钟才能阅读完成。
hello,各位小伙伴们,上午好~
昨晚生产零碎机房切换,又度过了一个不眠之夜。趁着这段无聊工夫,分享一下前一段时间 RocketMQ 踩坑经验
太惨了!!!早上刚躺下睡了两小时,就被一通电话幸运起来查看问题。
前言
事件是这样的,前端工夫咱们有个新业务上线,这个业务须要监听领取胜利的 mq 音讯,而后向绑定的音箱推送音讯。这样用户在领取实现之后,商家端就就能够收到收款播报。
起初咱们在测试环境的测试的时候,所有流程十分顺利,没有任何问题。然而等到咱们公布上线之后,却呈现了问题。
一笔领取胜利之后,音箱没有收回收款胜利的播报。所有流程排查下来之后,这才发现原来 MQ 生产端没有失常在生产音讯。
开始排查问题,第一想到的是生产端是不是公布失败了,然而查看相干日志,并没有任何异样。
登录 MQ 控制台,尝试手动从新公布音讯,神奇的事来了,生产端胜利收到音讯。
总结当初的问题,下文开始排查。
- MQ 生产端利用没有异样,然而无奈失常生产
- MQ 控制台发送音讯,生产端能够胜利生产音讯
排查问题
刚开始排查的时候,因为没有任何异样业务日志能够定位问题,所以问题排查起来十分困难。
排查了两天了,想过各种问题。比方以后生产端应用 RocketMQ 客户端版本比拟高,是不是版本兼容性导致的问题呢?
于是升高生产端的版本,从新公布之后,问题仍然存在。
没方法,只好应用 Google 大法了。
通过搜寻发现,原来默认状况下 rockmq 客户端的日志将会独自打印输出,日志文件地位如下:
${user.home}/logs/rocketmqlogs
下图为过后的日志截图:
能够看到生产端尝试连贯一个 20878 的端口,然而因为网络问题,始终连贯失败。
那这个 20878 是什么端口?
咱们并没有被动配置这个端口,然而 rocketmq broker 配置的端口为 20880。
搜寻发现,原来 rocketmq broker 默认将会启动三个通信端口:
第一个是 rocketmq broker 配置文件上配置的端口,默认端口为 10911,这里咱们批改成了 20880。
第二个是 rockemq broker vip 通道端口,这个端口将会在第一个端口根底上减 2,即 20878。
第三个是 rockemq broker 用户主从数据同步的端口,这个端口将会在第一个端口根底上加 1,即 20881。
大略晓得问题,解决办法就很简略了,要么防火墙关上 29878 网络端口的限度,要么敞开应用 vip 端口。
RocketMQ 客户端提供两种形式敞开应用 vip 端口。
- 代码被动禁止应用 vip 端口,配置如下:
## 生产端
DefaultMQPushConsumer#setVipChannelEnabled(false)
## 生产端
DefaultMQProducer#setVipChannelEnabled(false);
- 设置 JVM 参数,禁用 vip 端口
-Dcom.rocketmq.sendMessageWithVIPChannel=false
源码剖析
尽管问题解决了,然而上述问题实质起因还没有找到。所以这次咱们就从源码登程,寻根究底。
为什么 vip 端口网络不通将会导致消费者不能失常生产?
从 rocketmq 谬误日志,咱们能够看到报错代码位于 RebalanceService
类中。
这里次要用来执行 topic Rebalance(重均衡)。
首先咱们来理解一下,Rebalance
目标是为什么了。
假如以后 rocketmq broker 端存在一个 topic,领有四个队列,关系如下:
此时如果有一个消费者应用集群模式生产音讯,那么它将须要负责生产所有队列中的音讯。
当咱们再减少一个消费者生产音讯时,此时生产端将会主动进行重均衡,默认状况下将会应用均匀分配原则。
能够看到 Rebalance
机制能够晋升的音讯的并行处理机制。
rocketmq 生产端启动时竟会触发 Rebalance
机制。接着,咱们依据源码次要看下 Rebalance
主流程,代码位于RebalanceImpl#rebalanceByTopic
。
通常咱们应用集群生产模式,所以这里次要看集群模式下 Rebalance
过程。
上述代码整体流程如下:
- 首先获取 Rebalance 过程所需元数据,包含 Topic 下的队列信息汇合以及消费者组下的消费者实例 id 信息汇合
- 两者都存在的状况下,将会依照肯定策略将队列信息调配给每个消费者,默认依照
AllocateMessageQueueAveragely
,即均匀分配原则 - 将预调配后果尝试更新
ProcessQueue Table
, 如果有更新将会把新的队列在退出异步生产流程。
后续音讯流程就不看源码,比较复杂,网上找了一张音讯生产流程图:
能够看到,因为网络端口问题,无奈失常获取所有消费者 ID 汇合,这就导致无奈失常调配队列信息。
List<String> cidAll = this.mQClientFactory.findConsumerIdList(topic, consumerGroup);
因为未被调配任一队列,生产端程序也就业务无奈失常拉取音讯。
为什么 mq 控制台从新发送的音讯消费者能够收到?
rocketmq 控制台从新发送音讯代码如下:
MessageService
将会把音讯的元数据封装一个 CONSUME_MESSAGE_DIRECTLY
类型的申请,接着调用 rocketmq 提供的 admin API,给 rocketmq broker 发送申请。
broker 端收到申请之后,将会查问音讯,而后再向生产端发动 CONSUME_MESSAGE_DIRECTLY
申请。生产端承受到音讯申请之后,将会间接音讯这条音讯。
为什么 broker 将会启动两个端口?
rocketmq broker 尽管启动了两个端口,然而从 rocketmq broker 的源码能够发现这两个端口启动之后起到作用是一样的。
那为什么开启两个监听端口那?我想很多同学应该也有这个纳闷,这里给出一个开发者解释答案。
https://github.com/apache/roc…
一般的端口将会承载所有音讯网络申请,如果此时申请十分忙碌,broker 端的所有 I/O 线程可能都在执行申请,这就会导致后续网络申请进入队列,从而导致音讯申请执行迟缓。
这对于生产者来说,可能是一个致命的问题,因为音讯生产者通常音讯发送延时要低。
这种状况下,咱们就能够将音讯发送到 VIP 端口,从而升高音讯发送的延时。
默认状况下,rocketmq 客户端的 vipChannel
配置为 true
。
private boolean vipChannelEnabled = Boolean.parseBoolean(System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true"));
生产者的发送音讯,消费者获取元数据信息等申请默认将会应用 vip
端口。
不过这里须要留神一点,消费者拉取音讯,将不会应用vip
端口。
尽管这个设计很奇妙,然而说实话集体感觉这个配置权限应该交给开发者本人去配置,而不是默认开启。
因为不相熟的状况下还是很容易踩坑的,默认状况下,大家应该只相熟 9876 与 10911 这两个端口。
rocketmq 4.5.1 版本之后,vipChannel
配置被批改为 false
,这时是否应用 vip 端口真正交给开发者本人
如果此时想开启,须要被动 API 参数,或者 JVM 参数减少 -Dcom.rocketmq.sendMessageWithVIPChannel=true
总结
明天的问题次要因为 VIP 端口无奈连贯,从而导致生产端无奈失常生产音讯。尽管最初的解决办法非常简单,然而这个排查过程真的很难。
咱们平时在应用 rocketmq 过程中,通常只有设置 nameserver 的配置即可,broker 等地址信息将会主动从 nameserver 获取。这就间接导致了,咱们可能只理解 9876 这个端口。
生产环境因为网络安全问题,个别不会凋谢全副的端口。所以,咱们在应用 rocketmq 的过程,须要理解以下四个端口,别离为(默认配置):
- 9876:nameserver 监听端口
- 10911:broker 监听端口
- 10909:broker vip 监听端口
- 10912:broker HA 端口,用于主从同步
生产应用 rocketmq 过程,如果碰到诡问题,无妨尝试 telnet 看下网关连通性。另外还能够通过查看 rocketmq 本身日志,确定问题,日志地位位于:
${user.home}/logs/rocketmqlogs
好了,明天文章就到这里。我是楼下小黑哥,你晓得的越多,你不晓得的就越多。
下周见~
欢送关注我的公众号:程序通事,取得日常干货推送。如果您对我的专题内容感兴趣,也能够关注我的博客:studyidea.cn