RocketMQ 该不该上,上线后先守住什么
RocketMQ 该不该上,上线后先守住什么
这篇讲把 RocketMQ 装起来、接进业务、再看得住的过程,不分析源码。
先把一个前提说清:消息队列解决的是系统之间不必马上同步的问题,不是所有性能问题的通用答案。
一、先弄清消息队列替你挡了什么
下单、发通知、记日志,如果都塞在一个请求里,任何一步慢了,用户就得等。
消息队列,说白了就是一个中间存放处:发送方先把消息放进去,接收方按自己的节奏取出来处理。
它带来三样东西:削峰(也就是忙时先把活存起来)、解耦(也就是发送方和接收方不必互相等着)、可重放(也就是出了问题还能再处理一遍)。
代价是系统多了一层,消息可能重复、可能延迟,排查也比直接调用麻烦。
二、四个角色各自负责什么
RocketMQ 把参与者分成四类:名称服务、broker、生产者、消费者。
broker 是消息真正存下来和转发出去的那一层,可以理解成消息服务器。
生产者负责把消息发出去,消费者负责把消息取走并处理。
名称服务只回答一个问题:某个主题的消息,该去哪个 broker 找。
原文还提到几个概念:主题(Topic,消息的分类)、队列(Queue,主题里的分区)、分组(Group,生产或消费的一方)。
三、名称服务为什么不存消息
名称服务几乎不存业务数据,节点之间也不互相同步。
正因为不存消息,它可以部署多个,挂掉一个不影响消息本身。
生产者和消费者都先连名称服务,拿到路由信息,再去找对应的 broker。
这一步是启动顺序的根源:名称服务没起来,后面的角色找不到路。
四、broker 是真正存消息的那一层
broker 负责接收、存储、拉取和转发消息。
它可以用内存存,也可以落盘;落盘的意义是进程重启后消息还在。
原文称它提供不丢失、不重复的传递保证;业务侧仍要按同一条消息可能收到两次来设计,不能只靠中间件。
broker 还能按配置决定消费者从主节点还是从节点订阅消息。
五、生产者怎么找到 broker
生产者启动后,会随机连一个名称服务节点,保持长连接。
它定期从名称服务读取主题的路由信息,再和提供该主题服务的主 broker 建立长连接。
之后它还会定时向主 broker 发心跳,让 broker 知道这个生产者还活着。
对业务代码来说,这一层通常被封装成一个发送方法,调用方只需要给主题和消息内容。
六、消费者为什么能同时连主从
消费者同样先连名称服务,拿到路由信息。
它既可能连主 broker,也可能连从 broker,具体看 broker 的配置。
这也意味着,主节点出问题时,消费不一定立刻停。
原文特别强调,消费者会同时连着主 broker 和从 broker,并定时发心跳。
七、消息类型决定业务怎么用
RocketMQ 支持普通消息、顺序消息、事务消息、批量消息、定时消息和消息回溯。
顺序消息适合有先后要求的事,比如先创建订单再扣库存。
事务消息适合本地操作和发消息必须一起成功或一起失败的场景。
定时消息适合到期提醒,消息回溯适合补处理。
选哪种,不取决于功能多,而取决于业务能不能接受重复、延迟和乱序。
八、单机部署前先建好日志目录
下载之后,先在 RocketMQ 目录下建一个 logs 文件夹,日志默认往那里写。
没有这个目录,启动脚本可能直接失败,报错还不一定指向目录。
单机部署适合开发和验证,不适合承担生产流量。
原文给的启动方式是后台运行,名称服务和 broker 各起一个进程。
九、启动顺序和关闭顺序不能反
先起名称服务,再起 broker。
broker 可以带配置文件启动,原文用的是 conf 目录下的 broker.conf。
关闭时反过来:先关 broker,再关名称服务。
顺序反了,最轻是日志里一片连接失败,重一点是消息没落盘就被中断。
十、SpringBoot 接入只改三处
第一处是依赖:引入 RocketMQ 的 SpringBoot 启动器,版本用一个属性统一管理。
第二处是地址:在配置文件里写名称服务的地址和端口 9876,再给生产者一个分组名,原文用的是 aryee-message-group。
第三处是代码:生产者一个发送入口,消费者一个监听类。
原文提醒,示例代码是按某个多服务项目封装的,直接复制到别的项目里不一定能用。
十一、生产者这层要守住什么
生产者只负责把消息发出去,不负责保证业务一定执行成功。
主题名要稳定,不能把用户输入直接拼进主题名。
消息体要带业务主键,方便消费端查数据和去重。
发送失败要有重试和告警,不能只打一行日志。
十二、消费者这层要守住什么
原文的消费者示例监听主题 wx-cp-app-msg-topic,消费分组是 wx-cp-app-msg。
它从消息体里取手机号,查对应的企业微信用户,再决定消息发给谁。
如果没有指定接收方,示例里默认发给编号 14 的部门。
如果消息里带群聊标识,就走群消息;否则走应用消息。
这段代码说明一件事:消费端往往要补业务规则,不能只把消息打印出来。
十三、控制台怎么装、看什么
控制台项目在 GitHub 上,下载后自己编译成 jar。
原文用的版本是 1.0.0,启动时指定名称服务地址 127.0.0.1:9876 和端口 8000。
日志可以重定向到 RocketMQ 4.9.0 目录下的 logs/dashboard.log。
控制台主要看三件事:主题有没有积压、消费者还在不在线、broker 状态是否正常。
十四、端口和版本上的两个坑
第一个坑是端口:原文正文写启动端口 8090,示例命令写的是 8000,两个数对不上。
落地时以实际命令为准,并且确认这个端口没有被别的服务占用。
第二个坑是版本:控制台 1.0.0 和 RocketMQ 4.9.0 是原文的组合,换版本时要重新核对兼容性。
不要只看文档里的一句推荐,启动日志和实际连接成功才算数。
十五、什么时候不该上 RocketMQ
如果只是两个内部模块传个通知,直接调用或一张数据库表就够了。
如果团队没有人能维护 broker、处理积压和排查消息丢失,先别上。
如果业务不能接受重复消息,又没人愿意在消费端做去重,也不适合。
消息队列解决的是系统之间的协作问题,不是所有性能问题的通用答案。
本文作者:Aryee 发布时间:2023-11-12 15:03
本文出处:ARYEE.cn 固定链接:https://www.aryee.cn/archives/rocketmq.html
转载或引用请连这一行一起带走;文中的代码与结论按当时环境成立,组件升级后请以官方文档为准。