从 grpc 端口到 topic 配置的完整踩坑实录
关键词:rocketmq 5.x、spring boot、grpc、producer failed、no topic route info
适用版本:rocketmq 5.3.x + rocketmq-client-java 5.x
一、问题背景
在使用 rocketmq 5.3.3 搭配 spring boot 开发消息生产者时,服务启动正常、控制台可访问、topic 也“看似”已经创建,但在真正发送消息时却频繁失败,典型报错如下:
expected the service producerimpl-0 [failed] to be running
或:
no topic route info in name server for the topic: rewre
更让人困惑的是:
- rocketmq console 可以正常访问
- nameserver 和 broker 都已启动
- topic 在控制台里“存在”
- producer 代码没有明显错误
但消息就是发不出去。
本文将完整复盘这个问题,并给出 rocketmq 5.x 下的正确使用姿势。
二、rocketmq 5.x 与 4.x 的本质差异(很多坑从这里开始)
1️⃣ 通信协议发生了根本变化
| 版本 | 通信方式 |
|---|---|
| rocketmq 4.x | 自定义 tcp 协议 |
| rocketmq 5.x | grpc |
👉 rocketmq 5.x 的 java client 完全基于 grpc
这意味着:
- nameserver
- broker
- client(producer / consumer)
三者之间必须能通过 grpc 端口通信
2️⃣ rocketmq 5.x 新增的关键端口
以 rocketmq 5.3.3 为例:
nameserver
| 端口 | 作用 |
|---|---|
| 9876 | 兼容旧协议(console / admin) |
| 8081 | ✅ grpc 端口(5.x client 必须) |
broker
| 端口 | 作用 |
|---|---|
| 10911 | 旧协议 |
| 8080 | ✅ grpc 端口(producer / consumer 真正使用) |
⚠️ 如果只暴露 9876 / 10911,而没暴露 8081 / 8080:
- console 能用
- topic 能看
- producer 一发消息就失败
三、问题一:producer failed —— 实际是 grpc 不通
典型异常
org.apache.rocketmq.shaded.io.grpc.statusruntimeexception: unavailable: network closed for unknown reason
本质原因
rocketmq 5.x client 通过 grpc 连接 broker,但 broker 的 grpc 端口未暴露或不可达
解决方式
在 docker / 容器环境中,必须显式暴露 grpc 端口:
# nameserver ports: - "9876:9876" - "8081:8081" # broker ports: - "10911:10911" - "8080:8080"
四、问题二:no topic route info —— 真正的大坑
在 grpc 问题解决后,紧接着会遇到第二个错误:
no topic route info in name server for the topic: rewre
表面含义
nameserver 中没有该 topic 的路由信息
但问题并不只是“没建 topic”这么简单。
五、致命配置错误:producer 默认 topic + 代码显式 topic 混用
1️⃣ 错误示例(问题根源)
rocketmq:
producer:
endpoints: 127.0.0.1:8081
group: dromara-producer-group
topic: rewre # ❌ producer 级别默认 topicdemo:
rocketmq:
normal-topic: normal-topicrocketmqclienttemplate.syncsendnormalmessage(normaltopic, message);
日志打印的是:
发送普通消息到主题: normal-topic
但异常却是:
no topic route info for topic: rewre
2️⃣ 为什么会这样?
这是 rocketmq 5.x client 的一个“隐式行为”:
如果在
rocketmq.producer.topic中配置了 topic,
producer 初始化和首次发送时,会优先拉取该 topic 的路由信息
即使你在 send() 时传入了别的 topic:
syncsendnormalmessage("normal-topic", ...)
👉 client 仍然会先去 nameserver 查询 rewre 的路由
如果 rewre 不存在:
40402 no topic route info
六、正确姿势:两种方案,只能选一种
✅ 方案一(强烈推荐):删除 producer 默认 topic
正确配置
rocketmq:
producer:
endpoints: 127.0.0.1:8081
group: dromara-producer-group
timeout: 10000
max-retry-times: 2
enable-ssl: falsetopic 全部由代码控制
syncsendnormalmessage(normaltopic, message); syncsenddelaymessage(delaytopic, message); syncsendfifomessage(fifotopic, message);
手动创建 topic(必须)
mqadmin updatetopic -n rmqnamesrv:9876 -c defaultcluster -t normal-topic
👉 这是官方示例和生产环境最推荐的方式
⚠️ 方案二(不推荐):只使用一个固定 topic
如果配置了:
rocketmq:
producer:
topic: rewre那么你必须:
- 代码中 只能发
rewre - nameserver 中 必须存在
rewre
syncsendnormalmessage("rewre", message);❌ 不适合多 topic、延时、事务、顺序消息场景
七、rocketmq 5.x 的几个重要认知纠正
1️⃣ rocketmq 5.x不会自动创建 topic
和 4.x 不同:
topic 必须提前创建,否则必定 40402
2️⃣ console 看到 ≠ client 能用
- console / mqadmin:走旧协议
- producer / consumer:走 grpc
👉 两个世界
3️⃣ 日志不一定可信,异常才是真相
日志打印 topic ≠ client 实际拉取路由的 topic
八、最终 checklist(上线前必查)
- nameserver 暴露 8081
- broker 暴露 8080
- 使用 rocketmq-client-java 5.x
- 未配置
rocketmq.producer.topic - 所有 topic 已通过
mqadmin updatetopic创建 - producer group 唯一
九、总结
rocketmq 5.x 并不是“不能用”,
而是 思维模型已经完全不同于 4.x。
真正的三大坑只有:
- grpc 端口
- topic 不自动创建
- producer 默认 topic 与 send topic 混用
只要理解了这三点,
rocketmq 5.x + spring boot 会非常稳定、清晰、现代化。
你这次踩的坑,非常值得被更多人看到。
到此这篇关于rocketmq 5.x + spring boot 发送消息失败全解析的文章就介绍到这了,更多相关rocketmq 5.x spring boot 发送消息失败内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论