关于java:贞炸了上线之后消息收不到了

46次阅读

共计 3522 个字符,预计需要花费 9 分钟才能阅读完成。

hello,各位小伙伴们,上午好~

昨晚生产零碎机房切换,又度过了一个不眠之夜。趁着这段无聊工夫,分享一下前一段时间 RocketMQ 踩坑经验

太惨了!!!早上刚躺下睡了两小时,就被一通电话幸运起来查看问题。

前言

事件是这样的,前端工夫咱们有个新业务上线,这个业务须要监听领取胜利的 mq 音讯,而后向绑定的音箱推送音讯。这样用户在领取实现之后,商家端就就能够收到收款播报。

起初咱们在测试环境的测试的时候,所有流程十分顺利,没有任何问题。然而等到咱们公布上线之后,却呈现了问题。

一笔领取胜利之后,音箱没有收回收款胜利的播报。所有流程排查下来之后,这才发现原来 MQ 生产端没有失常在生产音讯。

开始排查问题,第一想到的是生产端是不是公布失败了,然而查看相干日志,并没有任何异样。

登录 MQ 控制台,尝试手动从新公布音讯,神奇的事来了,生产端胜利收到音讯

总结当初的问题,下文开始排查。

  1. MQ 生产端利用没有异样,然而无奈失常生产
  2. 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 端口。

  1. 代码被动禁止应用 vip 端口,配置如下:
## 生产端
DefaultMQPushConsumer#setVipChannelEnabled(false)
## 生产端
DefaultMQProducer#setVipChannelEnabled(false);
  1. 设置 JVM 参数,禁用 vip 端口
-Dcom.rocketmq.sendMessageWithVIPChannel=false

源码剖析

尽管问题解决了,然而上述问题实质起因还没有找到。所以这次咱们就从源码登程,寻根究底。

为什么 vip 端口网络不通将会导致消费者不能失常生产?

从 rocketmq 谬误日志,咱们能够看到报错代码位于 RebalanceService 类中。

这里次要用来执行 topic Rebalance(重均衡)。

首先咱们来理解一下,Rebalance 目标是为什么了。

假如以后 rocketmq broker 端存在一个 topic,领有四个队列,关系如下:

此时如果有一个消费者应用集群模式生产音讯,那么它将须要负责生产所有队列中的音讯。

当咱们再减少一个消费者生产音讯时,此时生产端将会主动进行重均衡,默认状况下将会应用均匀分配原则。

能够看到 Rebalance 机制能够晋升的音讯的并行处理机制。

rocketmq 生产端启动时竟会触发 Rebalance 机制。接着,咱们依据源码次要看下 Rebalance 主流程,代码位于RebalanceImpl#rebalanceByTopic

通常咱们应用集群生产模式,所以这里次要看集群模式下 Rebalance 过程。

上述代码整体流程如下:

  1. 首先获取 Rebalance 过程所需元数据,包含 Topic 下的队列信息汇合以及消费者组下的消费者实例 id 信息汇合
  2. 两者都存在的状况下,将会依照肯定策略将队列信息调配给每个消费者,默认依照 AllocateMessageQueueAveragely,即均匀分配原则
  3. 将预调配后果尝试更新 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

正文完
 0