Skip to content

虚拟机安装RocketMQ

虚拟机安装比 Docker 更接近真实服务器环境,适合学习 RocketMQ 的进程、端口、配置文件、日志目录和 JVM 参数。它解决的是“知道服务实际怎么启动、怎么排错”的问题,而不是只会复制容器命令。

安装链路总览

mermaid
flowchart TD
    A["准备 JDK"] --> B["下载二进制包"]
    B --> C["调整 NameServer JVM 参数"]
    C --> D["调整 Broker JVM 参数"]
    D --> E["启动 NameServer"]
    E --> F["配置 broker.conf"]
    F --> G["启动 Broker + Proxy"]
    G --> H["查看日志和端口"]
    H --> I["客户端发送 / 消费验证"]

为什么要先启动 NameServer:Broker 启动后需要向 NameServer 注册自己的地址、Topic 和队列信息;客户端也要通过 NameServer 或 Proxy 发现路由。如果 NameServer 没起来,Broker 即使进程存在,也无法形成完整的消息链路。

下载RocketMQ资源包

RocketMQ的安装包分为两种,二进制包和源码包。由于源码包需要编译所以这里选择下载二进制包,RocketMQ下载资源包下载

安装

RocketMQ是使用的Java语言开发的,所以需要安装Java运行时环境(要求1.8以上),安装环境这里省略。

为什么要改 JVM 参数

RocketMQ 默认参数更偏生产环境,NameServer、Broker 默认堆内存较大。学习用虚拟机通常只有 2G 或 4G 内存,如果不调整,常见后果是:

  1. 进程启动时直接因为内存不足失败。
  2. 虚拟机开始频繁 swap,命令看似执行了但服务响应很慢。
  3. Broker 启动后被系统 OOM Killer 杀掉。

所以本地学习可以先把堆调小,重点是跑通链路;生产环境不能简单照搬 512m,需要按消息量、堆外内存、页缓存和磁盘 IO 重新评估。

解压

shell
unzip rocketmq-all-5.2.0-source-release.zip

修改启动脚本

由于虚拟机内存比较小配置不太足而RocketMQ默认的配置(JVM内存配置为4g)又比较高一点所以需要配置下启动脚本。

  1. 进入文件目录

    shell
    cd rocketmq-all-5.2.0-bin-release/bin
  2. 编辑runserver.sh文件

    shell
    vim runserver.sh

    找到如下配置:

    shell
    choose_gc_options()
    {
      # Example of JAVA_MAJOR_VERSION value : '1', '9', '10', '11', ...
      # '1' means releases before Java 9
      JAVA_MAJOR_VERSION=$("$JAVA" -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F '.' '{print $1}')
      if [ -z "$JAVA_MAJOR_VERSION" ] || [ "$JAVA_MAJOR_VERSION" -lt "9" ] ; then
        JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
        JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC"
        JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
        JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"
      else
        JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
        JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"
        JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"
      fi
    }

    修改为如下配置(可根据自己需求修改大小,注意要根据Java版本修改,我使用的是8所以只修改了else里面的配置)。

    shell
    choose_gc_options()
    {
      # Example of JAVA_MAJOR_VERSION value : '1', '9', '10', '11', ...
      # '1' means releases before Java 9
      JAVA_MAJOR_VERSION=$("$JAVA" -version 2>&1 | awk -F '"' '/version/ {print $2}' | awk -F '.' '{print $1}')
      if [ -z "$JAVA_MAJOR_VERSION" ] || [ "$JAVA_MAJOR_VERSION" -lt "9" ] ; then
        JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
        JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC"
        JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
        JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m"
      else
        JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
        #JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
        #JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0"
        #JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M"
      fi
    }
  3. 编辑runbroker.sh

    shell
    vim runbroker.sh

    找到如下配置:

    shell
    choose_gc_options
    JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g"
    JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
    JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
    JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
    JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"

    修改为如下:

    shell
    JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m"
    JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow"
    JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch"
    JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=15g"
    JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking"

启动

启动NameServer

启动命令

shell
cd rocketmq-all-5.2.0-bin-release
nohup sh bin/mqnamesrv >mqnamesrv.log 2>&1 &

验证启动情况

shell
tail -f -n 500 mqnamesrv.log

一下日志表示启动成功

shell
The Name Server boot success. serializeType=JSON, address 0.0.0.0:9876

启动 Broker消息存储中心和Proxy代理

修改broker配置文件

shell
cd conf
vim broker.conf

修改配置如下:

shell
# 开启自动创建主题
autoCreateTopicEnable=true
brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
# 定义服务地址,主存地址
namesrvAddr=158.50.0.2:9876
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH

修改proxy配置文件

如果不修改配置文件则默认会使用8080这将会和rocketmq-dashboard端口冲突,当然也可以选择修改rocketmq-dashboard端口。

remotingListenPort:远程监听端口

grpcServerPort: grpc服务端口 //用于客户端连接(代理端口号)

json
{
  "rocketMQClusterName": "DefaultCluster",
  "remotingListenPort": 9080,
  "grpcServerPort": 9081
}

启动Broker

shell
# 启动(不使用代理)
nohup sh bin/mqbroker -n localhost:9876 >mqbroker.log 2>&1 &
# 启动 Broker+Proxy
nohup sh bin/mqbroker -n localhost:9876 --enable-proxy &
# 指定配置文件启动(broker默认使用的端口是10911,我们也可以在配置文件修改端口)
nohup sh bin/mqbroker -n localhost:9876 -c conf/broker.conf --enable-proxy &

验证启动情况

shell
tail -f -n 500 nohup.out

日志输出如下表示启动成功。

txt
Thu Jul 11 09:53:08 CST 2024 rocketmq-proxy startup successfully

组件启动原理

mermaid
flowchart TD
    A["mqnamesrv 监听 9876"] --> B["mqbroker 启动"]
    B --> C["读取 broker.conf"]
    C --> D["向 NameServer 注册 Broker 地址"]
    D --> E["创建或加载 CommitLog / ConsumeQueue"]
    E --> F["Proxy 暴露客户端接入端口"]
    F --> G["Producer / Consumer 建立连接"]

Broker 是消息真正落盘的地方。RocketMQ 写入消息时,会先写 CommitLog,再构建 ConsumeQueue 供消费者按队列读取。NameServer 不保存消息,它只是路由中心;所以排查“消息是否丢失”要看 Broker 日志和存储目录,而不是只看 NameServer。

常见风险和排查

现象常见原因排查方式
NameServer 启动失败JDK 未安装、JAVA_HOME 错误、内存不足java -version、查看 mqnamesrv.log
Broker 启动失败JVM 参数过大、namesrvAddr 写错、端口冲突tail -f mqbroker.lognetstat -lntp
客户端连不上防火墙未放行、Broker 注册了错误 IP检查 brokerIP1、开放 9876/10911/Proxy 端口
Dashboard 看不到 BrokerBroker 没注册到 NameServer查看 Broker 日志里的 register 信息
重启后消息不见存储目录被清理或启动了新的空目录检查 storePathRootDir 和磁盘挂载

最小验证 Demo

启动完成后至少做三件事:

shell
jps
tail -n 100 mqnamesrv.log
tail -n 100 mqbroker.log

如果端口正常,应该能看到 NameServer、Broker 相关 Java 进程。然后再用 Java Client 或控制台创建 Topic、发送消息、消费消息。安装不是目的,能解释“客户端如何找到 Broker、消息落在哪里、失败看哪份日志”才算真正学会。