细说RocketMQ双网卡问题
文章目录一、 为什么会出现“双网卡问题”关键冲突点Broker 汇报了错误的“身份证”二、 核心症状怎么判断自己踩坑了三、 完美解决方案方案 A如果是原生安装修改 broker.conf方案 B如果是 Docker / Docker Compose 安装最推荐四、 必须要放行的“云服务器安全组”端口总结口诀在分布式中间件如 RocketMQ、Kafka 等的部署中“双网卡问题”或者叫内外网隔离、多网络接口问题是把中间件部署在远端云服务器而本地 Spring Boot 去连接时最经典、最容易让人抓狂的坑。它的核心表现通常是明明 Nacos 能连上RocketMQ 的 Namesrv 也能连上但一发送消息或者消费消息就直接报超时Timeout或连接拒绝Connection Refused。下面我们用最通俗的语言彻底拆解这个问题的底层原理和解决方案。一、 为什么会出现“双网卡问题”在阿里云等云服务器ECS上通常存在两块“虚拟网卡”内网网卡Private IP比如172.19.xx.xx。这是云厂商机房内部通信用的速度极快内网千兆/万兆且不花流量费。公网网卡Public IP比如47.98.xx.xx。这是暴露给互联网的你本地电脑连接服务器、以及用户访问网站都走这个 IP。关键冲突点Broker 汇报了错误的“身份证”RocketMQ 的架构是NameServer注册中心负责管理路由Broker数据节点负责真正存取消息。默认情况当你在云服务器上启动 RocketMQ Broker 时它默认会去抓取服务器的内网 IP因为在服务器看来内网网卡才是它的主网卡。注册阶段Broker 向 NameServer 报到说“我叫 Broker-A我的地址是172.19.xx.xx:10911。”本地连接你本地的 Spring Boot 启动了配置了 NameServer 的公网 IP47.98.xx.xx。连接成功死锁发生Spring Boot 问 NameServer“我要发消息请问 Broker 在哪” NameServer 极为诚实地把刚才 Broker 注册的地址丢给本地“Broker 在172.19.xx.xx:10911你去吧。”崩溃你的本地电脑在互联网上怎么可能直接访问到阿里云机房内部的172.19.xx.xx呢于是本地 Spring Boot 开始疯狂尝试连接这个内网 IP直到连接超时报错。二、 核心症状怎么判断自己踩坑了如果你遇到以下现象99% 就是双网卡/内外网路由问题测试连接正常用telnet 47.98.xx.xx 9876NameServer 端口是通的。控制台正常部署在同台服务器上的 RocketMQ Dashboard控制台能正常看到集群和 Topic。唯独本地代码报错本地 Spring Boot 生产者发送消息时日志卡住几秒后抛出RemotingConnectException: connect to 172.19.xx.xx:10911 failed。注意看报错信息里的 IP如果变成了服务器的内网 IP就是此问题。三、 完美解决方案解决这个问题的核心逻辑非常简单强行指定 Broker 对外宣布的“身份证”为公网 IP。针对你使用Docker或原生安装修改方式略有不同方案 A如果是原生安装修改broker.conf找到你 RocketMQ 的配置文件通常在conf/2m-2s-async/或自定义路径下的broker.conf在文件末尾显式添加一行配置# 关键配置强行指定 Broker 对外暴露的 IP 为你的云服务器公网 IP brokerIP1 47.98.xx.xx # 如果你要做主从或者有特殊监听需求可以把 brokerIP2 也配上一般配 brokerIP1 即可 # brokerIP2 47.98.xx.xx注意启动 Broker 的时候必须带上-c参数指定这个配置文件否则配置不生效nohupshmqbroker-nlocalhost:9876-c../conf/broker.conf方案 B如果是 Docker / Docker Compose 安装最推荐如果你是用 Docker 部署的由于 Docker 容器内部还有一套虚拟网络更容易触发这个问题Broker 会把 Docker 的容器内网 IP 如172.17.0.x注册过去。在 Docker 启动命令中通过-c或者环境变量将brokerIP1传进去。Docker Run 示例dockerrun-d\--namermqbroker\-p10911:10911-p10909:10909\vincenzopalazzo/rocketmq:v5.1.0\shmqbroker-n47.98.xx.xx:9876-c/opt/rocketmq/conf/broker.conf--parambrokerIP147.98.xx.xxDocker Compose 示例最直观在映射的broker.conf挂载文件中写死brokerIP1你的公网IP或者在command启动命令中注入version:3.5services:rmqnamesrv:image:apache/rocketmq:5.1.0container_name:rmqnamesrvports:-9876:9876command:sh mqnamesrvrmqbroker:image:apache/rocketmq:5.1.0container_name:rmqbrokerports:-10909:10909-10911:10911environment:-NAMESRV_ADDRrmqnamesrv:9876# 核心就在最后这一句强行指定当前 Broker 注册上去的 IP 是公网公网 IPcommand:sh mqbroker-c /home/rocketmq/rocketmq-5.1.0/conf/broker.conf--param brokerIP147.98.xx.xxdepends_on:-rmqnamesrv四、 必须要放行的“云服务器安全组”端口改完配置后本地要成功通信还需要在阿里云/腾讯云后台放行以下几个端口。RocketMQ 用的端口比普通中间件多少放一个都会失败9876NameServer 的端口本地 Spring Boot 建立初步连接、拉取路由表用。10911Broker 的默认监听端口本地非 VIP 通道发送/消费消息的核心通道。10909Broker 的VIP 通道端口RocketMQ 默认开启 VIP 通道如果你的客户端没显式关闭 VIP 通道消息会往这个端口发。很多人只放行了 10911 没放行 10909结果依然超时。8080/8081针对 RocketMQ 5.x 纯 gRPC 模式如果你使用的是最新的 RocketMQ 5.x 并且使用了新的 Proxy 模式走的是 gRPC 协议需要开放对应的 Proxy 端口默认 8081。总结口诀本地连远端Broker 别偷懒莫报内网号公网 IP 填上面brokerIP1九八七六连名字一零九一送消息还有一零九零九安全组里别漏失