hello,各位小伙伴们,上午好~ 昨晚生产系统机房切换,又度过了一个不眠之夜。趁着这段无聊时间,分享一下前一段时间 RocketMQ 踩坑经历

欢迎关注我的公众号:「程序通事」,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

前言

事情是这样的,前端时间我们有个新业务上线,这个业务需要监听支付成功的 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/rocketmq/issues/1510

普通的端口将会承载所有消息网络请求,如果此时请求非常繁忙,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

rocketmq获取消息id_贞炸了!上线之后,消息收不到了!相关推荐

  1. jmstemplate 获取队列id_学习Linux(38)消息队列

    消息队列.共享内存 和 信号量 被统称为 system-V IPC,V 是罗马数字 5,是 Unix 的AT&T 分支的其中一个版本,一般习惯称呼他们为 IPC 对象,这些对象的操作接口都比较 ...

  2. rocketmq 如何保证高可用_如何保证消息队列是高可用的

    为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑.再不然就是和运营聊聊天,写几个SQL,生成下报表 ...

  3. RocketMQ:Consumer概述及启动流程与消息拉取源码分析

    文章目录 Consumer 概述 消费者核心类 消费者启动流程 消息拉取 PullMessageService实现机制 ProcessQueue实现机制 消息拉取基本流程 客户端发起消息拉取请求 消息 ...

  4. RocketMQ消费失败如何处理?如何保证消费消息的幂等性?

    文章目录 1. 消息消费失败如何处理? 2. 如何保证消费消息的幂等性? 1. 消息消费失败如何处理? 当消费者从Broker获取到消息后会进行消费,并返回消费状态.如下代码所示 //broker推消 ...

  5. rocketmq 消息指定_rocketmq-常见问题总结(消息的顺序、重复、消费模式)

    参考: http://www.cnblogs.com/wxd0108/p/6038543.html https://www.cnblogs.com/520playboy/p/6750023.html ...

  6. RocketMQ消息消费源码分析(二消息的消费)

    首先回到DefaultMQPushConsumerImpl  start方法 public synchronized void start() throws MQClientException {sw ...

  7. 苹果官网下架iPhone 8;破解百度网盘的Pandownload开发者被捕;三大运营商年内上线5G消息 | EA周报...

    EA周报 2020年4月17日 每个星期7分钟,元宝带你喝一杯IT人的浓缩咖啡,了解天下事.掌握IT核心技术. 热点大事件 谷歌收紧游戏商店规则,要求开发者提供免费试用细节 谷歌宣布了一系列政策调整, ...

  8. webScoket即时聊天,用户不在线时消息暂存,上线立马收到

    这个代码是用webScoket写的即时聊天通讯的,功能可群发单发,可对不在线用户发送消息时用户一上线立马就能收到消息,也可以查看未读数量,这个代码写了有一段时间了,忽然想起来就想着发上来记一下和交流一 ...

  9. RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ

    RabbitMQ,Apache的ActiveMQ,阿里RocketMQ,Kafka,ZeroMQ,MetaMQ,Redis也可实现消息队列,RabbitMQ的应用场景以及基本原理介绍,RabbitMQ ...

  10. RocketMQ源码(4)—Broker启动加载消息文件以及恢复数据源码【一万字】

    详细介绍了Broker启动加载消息文件以及恢复数据源码. 此前我们学习了Broker的启动源码:RocketMQ源码(3)-Broker启动流程源码解析[一万字],Broker的启动过程中,在Defa ...

最新文章

  1. leetcode -- 3 sum
  2. GNU make manual 翻译(二十六)
  3. selenium webdriver你使用的是不受支持的命令行标记
  4. Citrix XenApp Hotfix Rollup Pack部署最佳实践
  5. wxWidgets:wxPropertyGrid概述
  6. git移除某文件夹的版本控制
  7. 西南交大计算机组成原理考试大纲,西南交大计算机组成原理实验二七段LED数码管显示译码器的设计.docx...
  8. TC工具后台模式_C++资深开发工程师带你深入浅出了解Linux后台开发
  9. 【渝粤教育】国家开放大学2018年春季 0043-22T计算机文化 参考试题
  10. inotify用法简介及结合rsync实现主机间的文件实时同步
  11. hadoop--MapReduce_WordCount词频统计案例
  12. 卸载Android虚拟机里的项目(cmd)
  13. “萝莉变大妈”事件系主播策划!斗鱼出拳:永久封停!
  14. 致命错误: 在类路径或引导类路径中找不到程序包 java.lang_如何提升店铺动态评分 需要提升可以找我...
  15. java hashcode相等_关于java:hashCode实现,用于“等于某些字段相等”
  16. 递归求解汉诺塔问题(C++)
  17. c#开发之八---mvc
  18. Cron 表达式解析,crontab表达式解析
  19. idea打包docker镜像
  20. 博应用教你使用华为nova3添加桌面小工具

热门文章

  1. sql中将字符串转换成日期
  2. Lighting build failed. Swarm failed to kick off UE4光照构建失败
  3. 全国计算机二级flash,教你如何在Flash当中制作插按钮动画
  4. 时差怎么理解_懂的人自然懂,不懂的人再多解释也有时差,故事只能说给懂的人听...
  5. N个元素中选最大最小
  6. React脚手架---CRA
  7. 什么是视频监控平台的平台对接
  8. 2022-2028年中国网络直播行业商业模式创新与投资机会深度研究报告
  9. Android Hybrid 方案之 离线文件加载
  10. 傅立叶变换之(二)—— 傅立叶级数