性能调优
RocketMQ 作为高性能消息中间件,合理的调优配置可以显著提升系统性能。本章将从 JVM、操作系统、Broker 三个层面介绍性能调优方法。
调优思路
性能调优需要遵循科学的流程:
调优原则:
- 先监控后调优,避免盲目修改
- 单一变量原则,每次只修改一个参数
- 记录修改前后数据,对比效果
- 生产环境修改前先在测试环境验证
JVM 调优
JVM 内存模型
RocketMQ Broker 的 JVM 内存模型如下:
Broker JVM 配置
修改 bin/runbroker.sh 文件:
# 推荐配置(16GB 内存机器)
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"
# 大内存机器(32GB+ 内存)
JAVA_OPT="${JAVA_OPT} -server -Xms16g -Xmx16g -Xmn8g"
# GC 配置
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m"
JAVA_OPT="${JAVA_OPT} -XX:InitiatingHeapOccupancyPercent=45"
JAVA_OPT="${JAVA_OPT} -XX:MaxGCPauseMillis=200"
# 元空间配置
JAVA_OPT="${JAVA_OPT} -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
# 直接内存配置(重要)
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=4g"
# GC 日志
JAVA_OPT="${JAVA_OPT} -Xlog:gc*:file=/dev/shm/mq_gc.log:time,tags:filecount=5,filesize=30m"
NameServer JVM 配置
修改 bin/runserver.sh 文件:
# NameServer 内存需求较小
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC"
JVM 参数详解
| 参数 | 说明 | 推荐值 |
|---|---|---|
-Xms | 堆内存初始大小 | 与 -Xmx 相同,避免动态扩容 |
-Xmx | 堆内存最大值 | 机器内存的 50% 左右 |
-Xmn | 年轻代大小 | 堆内存的 40%-50% |
-XX:MaxDirectMemorySize | 直接内存最大值 | 与消息传输量相关 |
-XX:+UseG1GC | 使用 G1 垃圾收集器 | JDK 9+ 默认 |
-XX:MaxGCPauseMillis | GC 最大停顿时间 | 200ms |
GC 调优
G1 GC 配置建议:
# G1 基础配置
-XX:+UseG1GC
-XX:G1HeapRegionSize=16m # Region 大小
-XX:InitiatingHeapOccupancyPercent=45 # 触发并发 GC 的堆占用率
-XX:MaxGCPauseMillis=200 # 最大 GC 停顿时间
-XX:G1ReservePercent=10 # 保留空间百分比
-XX:G1HeapWastePercent=5 # 允许浪费的堆百分比
# 并发线程数
-XX:ConcGCThreads=4 # 并发 GC 线程数
-XX:ParallelGCThreads=8 # 并行 GC 线程数
GC 日志分析:
# 查看 GC 日志
tail -f ~/logs/rocketmqlogs/gc.log
# 关注指标
# - GC 频率
# - GC 停顿时间
# - 老年代增长速度
操作系统调优
内核参数优化
修改 /etc/sysctl.conf:
# 网络参数优化
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
# TCP 参数优化
net.ipv4.tcp_max_syn_backlog = 65536
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 30
# 文件描述符限制
fs.file-max = 1000000
# 内存参数
vm.swappiness = 10
vm.dirty_ratio = 80
vm.dirty_background_ratio = 5
应用配置:
sysctl -p
文件描述符限制
修改 /etc/security/limits.conf:
# 添加以下内容
* soft nofile 65536
* hard nofile 65536
* soft nproc 65536
* hard nproc 65536
验证:
ulimit -n
# 输出: 65536
磁盘 IO 优化
1. 选择合适的磁盘
| 磁盘类型 | 随机读 IOPS | 顺序写吞吐 | 适用场景 |
|---|---|---|---|
| HDD | 80-150 | 150 MB/s | 低成本存储 |
| SATA SSD | 80,000+ | 500 MB/s | 一般生产环境 |
| NVMe SSD | 500,000+ | 3000 MB/s | 高性能场景 |
2. 文件系统选择
推荐使用 XFS 文件系统:
# 格式化磁盘
mkfs.xfs -f /dev/sdb
# 挂载选项
mount -o noatime,nodiratime,allocsize=64k /dev/sdb /data
3. IO 调度算法
# 查看当前调度算法
cat /sys/block/sdb/queue/scheduler
# 设置为 noop(SSD 推荐)
echo noop > /sys/block/sdb/queue/scheduler
内存优化
1. 关闭 Swap
# 临时关闭
swapoff -a
# 永久关闭,修改 /etc/fstab,注释 swap 行
# 或设置 swappiness
sysctl vm.swappiness=0
2. 使用大页内存
# 查看大页内存
cat /proc/meminfo | grep Huge
# 设置大页内存
echo 2048 > /proc/sys/vm/nr_hugepages
Broker 调优
存储配置
修改 conf/broker.conf:
# 存储路径配置
storePathRootDir = /data/rocketmq/store
storePathCommitLog = /data/rocketmq/store/commitlog
storePathConsumeQueue = /data/rocketmq/store/consumequeue
storePathIndex = /data/rocketmq/store/index
# CommitLog 文件大小
mappedFileSizeCommitLog = 1073741824 # 1GB
# ConsumeQueue 文件大小
mappedFileSizeConsumeQueue = 300000
# 刷盘配置
flushDiskType = ASYNC_FLUSH # 异步刷盘,性能更好
# 刷盘间隔
flushCommitLogTimed = true
flushCommitLogInterval = 500 # 500ms 刷盘一次
# 消费队列刷盘
flushConsumeQueueThoroughInterval = 60000 # 60秒
线程池配置
# 发送消息线程池
sendMessageThreadPoolNums = 16 # 发送线程数
# 拉取消息线程池
pullMessageThreadPoolNums = 16 # 拉取线程数
# 查询消息线程池
queryMessageThreadPoolNums = 8
# 管理线程池
adminBrokerThreadPoolNums = 16
# 客户端管理线程池
clientManageThreadPoolNums = 32
# 消费者管理线程池
consumerManageThreadPoolNums = 32
内存配置
# TransientStorePool 配置(堆外内存)
transientStorePoolEnable = true
transientStorePoolSize = 5 # 堆外内存池大小
# 消息索引配置
maxHashSlotNum = 2000000
maxIndexNum = 20000000
# 消息过滤配置
enableCalcFilterBitMap = true
expectConsumerNumUseFilter = 32
maxErrorRateOfBloomFilter = 20
网络配置
# 监听端口
listenPort = 10911
# HA 端口
haListenPort = 10912
# 发送消息缓冲区大小
socketSendBuffer = 65535
# 接收消息缓冲区大小
socketReceiveBuffer = 65535
# 服务端 Socket 超时
serverSocketRcvBufSize = 131072
serverSocketSndBufSize = 131072
# 客户端连接数限制
maxConnectionNumPerIp = 100
消息相关配置
# 最大消息大小
maxMessageSize = 4194304 # 4MB
# 消息压缩阈值
compressMsgBodyOverHowmuch = 4096 # 超过 4KB 压缩
# 消息轨迹开关
traceTopicEnable = false
# 消息定时清理
deleteWhen = 04 # 凌晨 4 点清理
fileReservedTime = 72 # 保留 72 小时
# 物理磁盘使用率告警阈值
diskMaxUsedSpaceRatio = 75
性能基准测试
测试工具
RocketMQ 提供了性能测试工具:
# 生产者性能测试
sh bin/mqadmin producer -n localhost:9876 -t TopicTest -w 64 -s 1024
# 消费者性能测试
sh bin/mqadmin consumer -n localhost:9876 -t TopicTest -g TestGroup -w 64
参数说明:
| 参数 | 说明 |
|---|---|
-n | NameServer 地址 |
-t | Topic 名称 |
-g | 消费组名称 |
-w | 线程数 |
-s | 消息大小(字节) |
性能指标
典型性能数据
测试环境:
- 机器配置:16 核 CPU,32GB 内存,NVMe SSD
- 消息大小:1KB
- 线程数:64
性能数据参考:
| 场景 | 发送 TPS | 消费 TPS | 平均延迟 |
|---|---|---|---|
| 单 Master | 80,000+ | 60,000+ | < 5ms |
| 异步复制 | 70,000+ | 55,000+ | < 10ms |
| 同步双写 | 50,000+ | 45,000+ | < 15ms |
常见性能问题
1. 发送消息延迟高
可能原因:
- 磁盘 IO 性能不足
- GC 频繁导致停顿
- 网络带宽不足
- 线程池配置不合理
排查步骤:
# 1. 检查磁盘 IO
iostat -x 1
# 2. 检查 GC 日志
tail -f ~/logs/rocketmqlogs/gc.log
# 3. 检查网络带宽
iftop -i eth0
# 4. 检查线程池状态
sh bin/mqadmin brokerStatus -n localhost:9876 -b broker-a
2. 消息堆积
可能原因:
- 消费者处理能力不足
- 消费者数量不够
- 下游系统响应慢
- 消息处理逻辑耗时
解决方案:
# 1. 增加消费者实例
# 2. 增加消费线程数
consumer.setConsumeThreadMin(64);
consumer.setConsumeThreadMax(128);
# 3. 优化消费逻辑
# - 减少数据库访问次数
# - 使用批量处理
# - 异步化非核心逻辑
# 4. 临时丢弃非重要消息
sh bin/mqadmin resetOffsetByTime -n localhost:9876 -g GroupName -t TopicName -s -1
3. 内存溢出
可能原因:
- 堆内存设置过小
- 消息堆积导致内存占用
- Direct Memory 不足
解决方案:
# 1. 调整堆内存
-Xms8g -Xmx8g
# 2. 调整 Direct Memory
-XX:MaxDirectMemorySize=4g
# 3. 开启堆外内存池
transientStorePoolEnable = true
# 4. 分析内存快照
jmap -dump:format=b,file=heap.hprof <pid>
调优配置清单
JVM 配置清单
- 堆内存大小设置为机器内存的 50% 左右
- 年轻代大小设置为堆内存的 40%-50%
- 使用 G1 垃圾收集器
- 设置合适的 MaxDirectMemorySize
- 开启 GC 日志
操作系统配置清单
- 关闭 Swap 或设置 vm.swappiness=10
- 增加文件描述符限制
- 优化网络内核参数
- 使用 XFS 文件系统
- SSD 使用 noop 调度算法
Broker 配置清单
- 设置合适的刷盘方式
- 调整线程池大小
- 开启堆外内存池
- 设置消息保留时间
- 配置磁盘告警阈值
小结
本章介绍了 RocketMQ 的性能调优方法:
- JVM 调优:堆内存、GC、直接内存配置
- 操作系统调优:内核参数、文件描述符、磁盘 IO
- Broker 调优:存储、线程池、网络配置
- 性能测试:基准测试工具和指标
- 问题排查:常见性能问题的原因和解决方案
性能调优是一个持续的过程,需要根据实际业务场景不断调整和优化。