RocketMQ 5.x + Spring Boot 發(fā)送消息失敗全解析
從 gRPC 端口到 Topic 配置的完整踩坑實錄
關(guān)鍵詞: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 開發(fā)消息生產(chǎn)者時,服務(wù)啟動正常、控制臺可訪問、Topic 也“看似”已經(jīng)創(chuàng)建,但在真正發(fā)送消息時卻頻繁失敗,典型報錯如下:
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 代碼沒有明顯錯誤
但消息就是發(fā)不出去。
本文將完整復(fù)盤這個問題,并給出 RocketMQ 5.x 下的正確使用姿勢。
二、RocketMQ 5.x 與 4.x 的本質(zhì)差異(很多坑從這里開始)
1?? 通信協(xié)議發(fā)生了根本變化
| 版本 | 通信方式 |
|---|---|
| RocketMQ 4.x | 自定義 TCP 協(xié)議 |
| RocketMQ 5.x | gRPC |
?? RocketMQ 5.x 的 Java Client 完全基于 gRPC
這意味著:
- NameServer
- Broker
- Client(Producer / Consumer)
三者之間必須能通過 gRPC 端口通信
2?? RocketMQ 5.x 新增的關(guān)鍵端口
以 RocketMQ 5.3.3 為例:
NameServer
| 端口 | 作用 |
|---|---|
| 9876 | 兼容舊協(xié)議(Console / Admin) |
| 8081 | ? gRPC 端口(5.x Client 必須) |
Broker
| 端口 | 作用 |
|---|---|
| 10911 | 舊協(xié)議 |
| 8080 | ? gRPC 端口(Producer / Consumer 真正使用) |
?? 如果只暴露 9876 / 10911,而沒暴露 8081 / 8080:
- Console 能用
- Topic 能看
- Producer 一發(fā)消息就失敗
三、問題一:Producer FAILED —— 實際是 gRPC 不通
典型異常
org.apache.rocketmq.shaded.io.grpc.StatusRuntimeException: UNAVAILABLE: Network closed for unknown reason
本質(zhì)原因
RocketMQ 5.x Client 通過 gRPC 連接 Broker,但 Broker 的 gRPC 端口未暴露或不可達(dá)
解決方式
在 Docker / 容器環(huán)境中,必須顯式暴露 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 默認(rèn) Topic + 代碼顯式 Topic 混用
1?? 錯誤示例(問題根源)
rocketmq:
producer:
endpoints: 127.0.0.1:8081
group: dromara-producer-group
topic: rewre # ? Producer 級別默認(rèn) topicdemo:
rocketmq:
normal-topic: normal-topicrocketMQClientTemplate.syncSendNormalMessage(normalTopic, message);
日志打印的是:
發(fā)送普通消息到主題: normal-topic
但異常卻是:
No topic route info for topic: rewre
2?? 為什么會這樣?
這是 RocketMQ 5.x Client 的一個“隱式行為”:
如果在
rocketmq.producer.topic中配置了 topic,
Producer 初始化和首次發(fā)送時,會優(yōu)先拉取該 topic 的路由信息
即使你在 send() 時傳入了別的 topic:
syncSendNormalMessage("normal-topic", ...)
?? Client 仍然會先去 NameServer 查詢 rewre 的路由
如果 rewre 不存在:
40402 No topic route info
六、正確姿勢:兩種方案,只能選一種
? 方案一(強(qiáng)烈推薦):刪除 Producer 默認(rèn) 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);
手動創(chuàng)建 topic(必須)
mqadmin updatetopic -n rmqnamesrv:9876 -c DefaultCluster -t normal-topic
?? 這是官方示例和生產(chǎn)環(huán)境最推薦的方式
?? 方案二(不推薦):只使用一個固定 topic
如果配置了:
rocketmq:
producer:
topic: rewre那么你必須:
- 代碼中 只能發(fā)
rewre - NameServer 中 必須存在
rewre
syncSendNormalMessage("rewre", message);? 不適合多 topic、延時、事務(wù)、順序消息場景
七、RocketMQ 5.x 的幾個重要認(rèn)知糾正
1?? RocketMQ 5.x不會自動創(chuàng)建 Topic
和 4.x 不同:
Topic 必須提前創(chuàng)建,否則必定 40402
2?? Console 看到 ≠ Client 能用
- Console / mqadmin:走舊協(xié)議
- Producer / Consumer:走 gRPC
?? 兩個世界
3?? 日志不一定可信,異常才是真相
日志打印 topic ≠ Client 實際拉取路由的 topic
八、最終 Checklist(上線前必查)
- NameServer 暴露 8081
- Broker 暴露 8080
- 使用 rocketmq-client-java 5.x
- 未配置
rocketmq.producer.topic - 所有 topic 已通過
mqadmin updatetopic創(chuàng)建 - Producer group 唯一
九、總結(jié)
RocketMQ 5.x 并不是“不能用”,
而是 思維模型已經(jīng)完全不同于 4.x。
真正的三大坑只有:
- gRPC 端口
- Topic 不自動創(chuàng)建
- Producer 默認(rèn) topic 與 send topic 混用
只要理解了這三點,
RocketMQ 5.x + Spring Boot 會非常穩(wěn)定、清晰、現(xiàn)代化。
你這次踩的坑,非常值得被更多人看到。
到此這篇關(guān)于RocketMQ 5.x + Spring Boot 發(fā)送消息失敗全解析的文章就介紹到這了,更多相關(guān)RocketMQ 5.x Spring Boot 發(fā)送消息失敗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis模糊查詢報錯:ParserException: not supported.pos&n
本文主要介紹了MyBatis模糊查詢報錯:ParserException: not supported.pos 問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
Mybatis基于MapperScan注解的動態(tài)代理加載機(jī)制詳解
這篇文章主要介紹了Mybatis基于MapperScan注解的動態(tài)代理加載機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01
Java讀取json數(shù)據(jù)并存入數(shù)據(jù)庫的操作代碼
很多朋友問大佬們JAVA怎么把json存入數(shù)據(jù)庫啊,這一問題就把我難倒了,糾結(jié)如何操作呢,下面小編把我的經(jīng)驗分享給大家,感興趣的朋友一起看看吧2021-08-08
SpringBoot啟動后執(zhí)行方法的五種實現(xiàn)方式
本文介紹了SpringBoot中五種在項目啟動后執(zhí)行方法的方式,包括實現(xiàn)CommandLineRunner和ApplicationRunner接口、實現(xiàn)ApplicationListener接口、使用@PostConstruct注解以及實現(xiàn)InitializingBean接口,每種方式都有其特點和適用場景2025-02-02
Java timezone設(shè)置和mybatis連接數(shù)據(jù)庫時區(qū)設(shè)置方式
這篇文章主要介紹了Java timezone設(shè)置和mybatis連接數(shù)據(jù)庫時區(qū)設(shè)置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09

