docker

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 云和虚拟化 > docker > Docker 部署 RocketMQ

Docker 部署 RocketMQ 5.1.0 踩坑指南从超时到 Console 连不上的完整解决方案

作者:程序员Terry

最近在项目中引入RocketMQ作为消息中间件,选择使用Docker容器化部署以简化环境搭建,本文给大家介绍Docker 部署 RocketMQ 5.1.0 踩坑指南从超时到 Console 连不上的完整解决方案,感兴趣的朋友跟随小编一起看看吧

前言

最近在项目中引入 RocketMQ 作为消息中间件,选择使用 Docker 容器化部署以简化环境搭建。本以为按照官方文档几条命令就能搞定,结果连续踩了两个大坑:先是生产者发送消息超时,修复后 Console 管理界面又连不上 Broker。

如果你也在用 Docker 部署 RocketMQ,或者正准备搭建,希望这篇实录能帮你避开我踩过的坑。

读完本文,你将掌握:

一、环境准备

1.1 创建独立网络

RocketMQ 的 NameServer、Broker、Console 三个组件需要网络互通,创建一个独立的 Docker 网络是最佳实践:

# 创建 rocketmq 网络
docker network create rocketmq
# 验证网络创建成功
docker inspect rocketmq

为什么需要独立网络?

1.2 拉取官方镜像

docker pull apache/rocketmq:5.1.0

本文使用 RocketMQ 5.1.0 版本,这是目前较新的稳定版本。5.x 引入了 Proxy 代理层,架构与 4.x 有较大变化,后续会详细说明。

1.3 目录规划

# NameServer 日志目录
mkdir -p /usr/local/rocketmq/nameserver/logs
chmod 777 -R /usr/local/rocketmq/nameserver/*
# Broker 日志和配置目录
mkdir -p /usr/local/rocketmq/broker/logs
mkdir -p /usr/local/rocketmq/broker/conf
chmod 777 -R /usr/local/rocketmq/broker/*

提示:使用 chmod 777 是为了让容器内的 rocketmq 用户有写入权限,生产环境建议通过用户组管理权限。

二、标准部署流程

2.1 部署 NameServer

NameServer 是什么?

NameServer 是 RocketMQ 的轻量级路由注册中心,类似于 Dubbo 的 Zookeeper,但更简单:

docker run -d --name mqnamesrv -p 9876:9876 --network rocketmq \
  -v /usr/local/rocketmq/nameserver/logs:/home/rocketmq/logs \
  -e "MAX_HEAP_SIZE=256M" \
  -e "HEAP_NEWSIZE=128M" \
  apache/rocketmq:5.1.0 sh mqnamesrv

验证启动:

docker logs mqnamesrv

看到 The Name Server boot success 字样即表示启动成功。

2.2 部署 Broker

Broker 与 Proxy 的关系

RocketMQ 5.x 引入了 Proxy 层,位于客户端和 Broker 之间:

Proxy 对外屏蔽了 NameServer、Broker 的概念,统一提供消息服务接口,同时支持多种协议(gRPC、HTTP 等)。

官方推荐使用 Local 模式部署,即 Broker 和 Proxy 同进程运行,减少网络开销。

docker run -d --name mqbroker -p 10911:10911 -p 10909:10909 --network rocketmq \
  -v /usr/local/rocketmq/broker/logs:/root/logs \
  -e "MAX_HEAP_SIZE=512M" \
  -e "HEAP_NEWSIZE=256M" \
  apache/rocketmq:5.1.0 sh mqbroker -n mqnamesrv:9876 --enable-proxy \
  autoCreateTopicEnable=true \
  -c /home/rocketmq/rocketmq-5.1.0/conf/broker.conf

端口说明:

验证启动:

docker exec -it mqbroker bash -c "tail -n 10 /home/rocketmq/logs/rocketmqlogs/proxy.log"

2.3 部署 Console 管理界面

RocketMQ Console 是官方推荐的第三方管理工具,提供图形化界面用于监控消息堆积、消费者状态等。

docker run -d --name mqconsole -p 8098:8080 --network rocketmq \
  -e "JAVA_OPTS=-Xmx256M -Xms256M -Xmn128M \
  -Drocketmq.namesrv.addr=mqnamesrv:9876 \
  -Dcom.rocketmq.sendMessageWithVIPChannel=false" \
  styletang/rocketmq-console-ng

访问 http://<宿主机IP>:8098 即可看到控制台。

三、第一个坑:生产者发送超时

3.1 问题现象

按照上述步骤部署后,Console 能正常连接,一切看起来很美好。但在 Spring Boot 应用中发送消息时:

rocketMQTemplate.syncSend("hotel-booking-test-topic:TEST_TAG", "Hello RocketMQ");

报错信息:

org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout
	at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendDefaultImpl

3.2 根因分析

通过排查日志和网络,发现问题出在 Broker IP 注册上:

问题链路:

  1. Broker 启动时,向 NameServer 注册自己的地址
  2. 默认情况下,Broker 使用容器的内部 IP(如 172.18.0.3)注册
  3. 当外部的生产者向 NameServer 查询路由时,得到的是容器 IP
  4. 生产者尝试连接 172.18.0.3:10911,但这个 IP 在宿主机网络中不可达
  5. 连接超时!

网络拓扑示意:

┌─────────────────┐
│  生产者(宿主机)  │
└────────┬────────┘
         │ 查询路由
         ↓
┌─────────────────┐
│  NameServer     │ → 返回 brokerIP=172.18.0.3
└─────────────────┘
         │
         │ 尝试连接 172.18.0.3:10911 ❌ (不可达)
         ↓
┌─────────────────┐
│ Broker 容器      │ 实际可访问: 宿主机IP:10911
│ IP: 172.18.0.3  │
└─────────────────┘

3.3 解决方案:配置 brokerIP1

让 Broker 向 NameServer 注册时,使用宿主机 IP 而非容器 IP。

步骤一:创建配置文件

# 在宿主机创建配置文件
cat > /usr/local/rocketmq/broker/conf/broker.conf << 'EOF'
brokerIP1=你的宿主机IP
autoCreateTopicEnable=true
EOF

重要brokerIP1 必须配置为宿主机的实际 IP,不能是 127.0.0.1 或容器 IP。

步骤二:重新部署 Broker(挂载配置文件)

# 停止并删除旧容器
docker stop mqbroker && docker rm mqbroker
# 重新运行,挂载配置文件
docker run -d --name mqbroker \
  -p 10911:10911 -p 10909:10909 \
  --network rocketmq \
  -v /usr/local/rocketmq/broker/logs:/root/logs \
  -v /usr/local/rocketmq/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.1.0/conf/broker.conf \
  -e "MAX_HEAP_SIZE=512M" \
  -e "HEAP_NEWSIZE=256M" \
  apache/rocketmq:5.1.0 sh mqbroker -n mqnamesrv:9876 \
  -c /home/rocketmq/rocketmq-5.1.0/conf/broker.conf

验证修复:

# 查看 Console 中的 Broker 信息
# 应该看到 brokerIP1 已经显示为宿主机 IP

此时,生产者应该可以正常发送消息了!

四、第二个坑:Console 连不上 Broker

4.1 问题现象

修复了生产者超时问题后,你以为一切正常了,结果打开 Console…

Console 状态:

Console 日志:

Error connecting to Broker: Connection refused

4.2 根因分析

这是一个典型的拆东墙补西墙问题:

配置 brokerIP1 前:

配置 brokerIP1 后:

网络冲突示意:

┌─────────────────┐
│ Console 容器     │ → 访问 mqbroker:10911 (容器网络)
└─────────────────┘
        │
        │ NameServer 返回: 宿主机IP:10911
        ↓
┌─────────────────┐
│ Broker 注册地址  │ = 宿主机IP:10911
└─────────────────┘
        │
        │ Console 尝试连接 宿主机IP:10911
        ↓
┌─────────────────┐
│ 网络路由问题      │ 容器内访问宿主机IP需要特殊配置
└─────────────────┘

4.3 终极解决方案:Console 使用 host 网络模式

让 Console 容器直接使用宿主机的网络栈,这样它可以通过 127.0.0.1:10911 访问 Broker(端口已映射到宿主机)。

# 停止并删除旧 Console
docker stop mqconsole && docker rm mqconsole
# 使用 host 网络模式重新部署
docker run -d --name mqconsole --network host \
  -e "JAVA_OPTS=-Xmx256M -Xms256M -Xmn128M \
  -Drocketmq.namesrv.addr=127.0.0.1:9876 \
  -Dcom.rocketmq.sendMessageWithVIPChannel=false" \
  styletang/rocketmq-console-ng

为什么这样能解决问题?

使用 --network host 后:

访问 Console:

# 不再需要端口映射,直接访问宿主机端口
# 假设 Console 默认端口是 8080
http://<宿主机IP>:8080

4.4 备用方案:本地路由转发(不推荐)

如果不使用 host 网络模式,也可以配置宿主机的路由规则,但配置较复杂:

# 启用本地路由转发
sysctl -w net.ipv4.conf.all.route_localnet=1
# 放通防火墙规则
iptables -I INPUT -d <宿主机IP> -p tcp --dport 10911 -j ACCEPT

建议:优先使用 host 网络模式,简单且不易出错。

五、完整可运行配置

5.1 一键部署脚本

将以下脚本保存为 deploy-rocketmq.sh,修改 BROKER_IP 为你的宿主机 IP 后执行:

#!/bin/bash
# ========== 配置区 ==========
BROKER_IP="192.168.1.100"  # 修改为你的宿主机 IP
# ===========================
# 1. 创建网络
docker network create rocketmq 2>/dev/null || echo "网络已存在"
# 2. 创建目录
mkdir -p /usr/local/rocketmq/nameserver/logs
mkdir -p /usr/local/rocketmq/broker/logs
mkdir -p /usr/local/rocketmq/broker/conf
chmod 777 -R /usr/local/rocketmq/*
# 3. 创建 Broker 配置文件
cat > /usr/local/rocketmq/broker/conf/broker.conf << EOF
brokerIP1=$BROKER_IP
autoCreateTopicEnable=true
namesrvAddr=mqnamesrv:9876
EOF
# 4. 启动 NameServer
docker run -d --name mqnamesrv -p 9876:9876 --network rocketmq \
  -v /usr/local/rocketmq/nameserver/logs:/home/rocketmq/logs \
  -e "MAX_HEAP_SIZE=256M" \
  -e "HEAP_NEWSIZE=128M" \
  apache/rocketmq:5.1.0 sh mqnamesrv
# 等待 NameServer 启动
sleep 5
# 5. 启动 Broker
docker run -d --name mqbroker \
  -p 10911:10911 -p 10909:10909 \
  --network rocketmq \
  -v /usr/local/rocketmq/broker/logs:/root/logs \
  -v /usr/local/rocketmq/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.1.0/conf/broker.conf \
  -e "MAX_HEAP_SIZE=512M" \
  -e "HEAP_NEWSIZE=256M" \
  apache/rocketmq:5.1.0 sh mqbroker -n mqnamesrv:9876 \
  -c /home/rocketmq/rocketmq-5.1.0/conf/broker.conf
# 等待 Broker 启动
sleep 10
# 6. 启动 Console(使用 host 网络)
docker run -d --name mqconsole --network host \
  -e "JAVA_OPTS=-Xmx256M -Xms256M -Xmn128M \
  -Drocketmq.namesrv.addr=127.0.0.1:9876 \
  -Dcom.rocketmq.sendMessageWithVIPChannel=false" \
  styletang/rocketmq-console-ng
echo "========== 部署完成 =========="
echo "NameServer: localhost:9876"
echo "Broker: $BROKER_IP:10911"
echo "Console: http://localhost:8080"
echo "============================"

5.2 Spring Boot 配置示例

# application.yml
rocketmq:
  name-server: localhost:9876
  producer:
    group: hotel-booking-producer-group
    send-message-timeout: 3000
    retry-times-when-send-failed: 2
// 发送消息示例
@Service
public class OrderService {
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    public void sendOrderMessage(Order order) {
        rocketMQTemplate.syncSend(
            "hotel-booking-test-topic:TEST_TAG",
            order,
            3000  // 超时时间 3 秒
        );
    }
}

5.3 验证命令清单

# 检查容器状态
docker ps -a | grep mq
# 查看 NameServer 日志
docker logs mqnamesrv
# 查看 Broker 日志
docker logs mqbroker
# 测试生产者连接
telnet <宿主机IP> 10911
# 查看 Console 中的 Broker 状态
# 访问 http://<宿主机IP>:8080,检查 "Broker" 菜单

六、最佳实践与避坑指南

6.1 生产环境建议

组件开发/测试环境生产环境
部署方式Docker 单机Docker Swarm / K8s 集群
NameServer1 个节点≥3 个节点(高可用)
Broker单 MasterMaster-Slave 组成集群
存储映射宿主机目录分布式存储 / PVC
JVM 内存256M~512M≥4G(根据消息量调整)
监控ConsolePrometheus + Grafana

6.2 常见错误对照表

错误信息可能原因解决方案
sendDefaultImpl call timeoutbrokerIP1 配置错误配置为宿主机 IP
Connection refused端口未映射或防火墙拦截检查 -p 参数和防火墙规则
Console 无法连接 Broker网络模式冲突Console 使用 --network host
No route info of this topicTopic 不存在启用 autoCreateTopicEnable=true
Broker 启动失败配置文件路径错误检查 -c 参数和挂载路径

6.3 Docker Compose 版本(推荐)

如果使用 Docker Compose,配置更简洁:

version: '3.8'
services:
  namesrv:
    image: apache/rocketmq:5.1.0
    container_name: mqnamesrv
    ports:
      - "9876:9876"
    environment:
      - MAX_HEAP_SIZE=256M
      - HEAP_NEWSIZE=128M
    networks:
      - rocketmq
    command: sh mqnamesrv
    volumes:
      - ./data/namesrv/logs:/home/rocketmq/logs
  broker:
    image: apache/rocketmq:5.1.0
    container_name: mqbroker
    ports:
      - "10911:10911"
      - "10909:10909"
    environment:
      - MAX_HEAP_SIZE=512M
      - HEAP_NEWSIZE=256M
    networks:
      - rocketmq
    command: sh mqbroker -n mqnamesrv:9876 -c /home/rocketmq/rocketmq-5.1.0/conf/broker.conf
    volumes:
      - ./data/broker/logs:/root/logs
      - ./data/broker/conf/broker.conf:/home/rocketmq/rocketmq-5.1.0/conf/broker.conf
    depends_on:
      - namesrv
  console:
    image: styletang/rocketmq-console-ng
    container_name: mqconsole
    network_mode: host
    environment:
      - JAVA_OPTS=-Xmx256M -Xms256M -Xmn128M -Drocketmq.namesrv.addr=127.0.0.1:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false
    depends_on:
      - namesrv
      - broker
networks:
  rocketmq:
    driver: bridge

启动:

# 确保 broker.conf 中的 brokerIP1 已配置
docker-compose up -d

总结

通过本文的实战记录,我们解决了 Docker 部署 RocketMQ 时的两个核心问题:

  1. 生产者超时:通过配置 brokerIP1 让 Broker 注册宿主机 IP
  2. Console 连不上:通过 --network host 让 Console 直接访问宿主机网络

到此这篇关于Docker 部署 RocketMQ 5.1.0 踩坑指南从超时到 Console 连不上的完整解决方案的文章就介绍到这了,更多相关Docker 部署 RocketMQ 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文