性能优化手册
# 前言
本文档介绍金蝶Apusic分布式消息队列for RocketMQ(Apusic Distributed Message Queue for RocketMQ,简称:ADMQ for RocketMQ)的性能优化最佳实践,帮助用户充分利用系统性能。
# 适用对象
本文档适用于IT信息化业务负责人、研发经理、软件项目经理、软件架构师、运维工程师。
# 相关文档
了解更多ADMQ for RocketMQ产品相关的信息,请参阅以下ADMQ for RocketMQ产品手册文档集:
| 序号 | 手册文档 | 说明 |
|---|---|---|
| 1 | 金蝶Apusic分布式消息队列for RocketMQ 快速使用手册 | 简单介绍了如何快速上手使用ADMQ for RocketMQ 。 |
| 2 | 金蝶Apusic分布式消息队列for RocketMQ 安装手册 | 详细介绍如何在各操作系统上安装ADMQ for RocketMQ,以及ADMQ for RocketMQ服务启停等操作。 |
| 3 | 金蝶Apusic分布式消息队列for RocketMQ 消息引擎用户手册 | 详细介绍 ADMQ for RocketMQ 消息引擎相关功能的使用、配置、管理及配套工具的使用方法。 |
| 4 | 金蝶Apusic分布式消息队列for RocketMQ 管控台用户手册 | 详细介绍ADMQ for RocketMQ管控台相关功能的使用和操作说明。 |
| 5 | 金蝶Apusic分布式消息队列for RocketMQ 开发手册 | 详细介绍基于各开发语言进行ADMQ for RocketMQ客户端应用开发的说明。 |
| 6 | 金蝶Apusic分布式消息队列for RocketMQ 迁移手册 | 详细介绍从RocketMQ迁移到ADMQ for RocketMQ的说明。 |
| 7 | 金蝶Apusic分布式消息队列for RocketMQ 运维手册 | 详细介绍ADMQ for RocketMQ的监控、运维、安全加固等运维说明。 |
| 8 | 金蝶Apusic分布式消息队列for RocketMQ 性能优化手册 | 详细介绍ADMQ for RocketMQ性能调优的说明。 |
# 技术支持
ADMQ for RocketMQ产品提供全面的技术支持服务,您可以通过以下方式获得技术支持:
- 网址:www.apusic.com
- 电话:400-855-5800
- 邮箱:support@apusic.com
- 金蝶云社区:https://vip.kingdee.com/?productId=73&productLineId=14&lang=zh-CN
您在取得技术支持时,请提供如下信息:
您的姓名
公司信息与联系方式
操作系统及其版本
产品版本号
出现异常及错误的日志、截图等详细信息
# 系统层面优化
# 操作系统优化
# 文件描述符
# 查看当前限制
ulimit -n
# 修改限制(/etc/security/limits.conf)
* soft nofile 65535
* hard nofile 65535
1
2
3
4
5
6
2
3
4
5
6
# 内核参数
# /etc/sysctl.conf
# 增加端口范围
net.ipv4.ip_local_port_range = 1024 65535
# TCP 连接优化
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.core.somaxconn = 65535
# 内存优化
vm.swappiness = 10
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
# 应用配置
sysctl -p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 磁盘优化
| 优化项 | 建议 |
|---|---|
| 文件系统 | 使用 XFS 文件系统 |
| 挂载选项 | noatime,nodiratime |
| 磁盘调度 | 使用 noop 或 deadline |
| RAID 配置 | 使用 RAID 10 或 RAID 0 |
| SSD 优化 | 启用 TRIM,预留 over-provisioning |
# 查看磁盘调度算法
cat /sys/block/sda/queue/scheduler
# 设置为 deadline
echo deadline > /sys/block/sda/queue/scheduler
# 挂载选项(/etc/fstab)
/dev/sda1 /data/rocketmq xfs noatime,nodiratime 0 0
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 网络优化
# 网络缓冲区
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
# TCP 优化
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_no_metrics_save = 1
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# RocketMQ 配置优化
# Broker 配置
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| sendMessageThreadPoolNums | 1 | CPU 核数 | 发送消息线程数 |
| pullMessageThreadPoolNums | 16+ | 根据负载调整 | 拉取消息线程数 |
| queryMessageThreadPoolNums | 8 | 根据负载调整 | 查询消息线程数 |
| adminBrokerThreadPoolNums | 16 | 根据负载调整 | 管理操作线程数 |
| brokerRole | ASYNC_MASTER | SYNC_MASTER | Broker 角色 |
| flushDiskType | ASYNC_FLUSH | SYNC_FLUSH | 刷盘方式 |
| flushIntervalCommitLog | 500ms | 根据可靠性要求 | CommitLog 刷盘间隔 |
| flushIntervalConsumeQueue | 1000ms | 根据可靠性要求 | ConsumeQueue 刷盘间隔 |
# broker.conf
sendMessageThreadPoolNums=16
pullMessageThreadPoolNums=16
brokerRole=SYNC_MASTER
flushDiskType=SYNC_FLUSH
flushIntervalCommitLog=500
flushIntervalConsumeQueue=1000
1
2
3
4
5
6
7
2
3
4
5
6
7
# 存储配置
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| mapedFileSizeCommitLog | 1GB | 1GB | CommitLog 文件大小 |
| mapedFileSizeConsumeQueue | 300MB | 300MB | ConsumeQueue 文件大小 |
| flushCommitLogTimed | false | false | 是否定时刷盘 |
| deleteWhen | 04 | 04 | 删除过期文件时间 |
| fileReservedTime | 72 | 根据磁盘容量 | 文件保留时间(小时) |
| diskMaxUsedSpaceRatio | 75 | 75 | 磁盘最大使用比例 |
# broker.conf
mapedFileSizeCommitLog=1073741824
mapedFileSizeConsumeQueue=300000000
deleteWhen=04
fileReservedTime=72
diskMaxUsedSpaceRatio=75
1
2
3
4
5
6
2
3
4
5
6
# JVM 配置
# NameServer JVM
# bin/runserver.sh
JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m"
JAVA_OPT="${JAVA_OPT} -XX:G1ReservePercent=25"
JAVA_OPT="${JAVA_OPT} -XX:InitiatingHeapOccupancyPercent=30"
1
2
3
4
5
2
3
4
5
# Broker JVM
# bin/runbroker.sh
JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"
JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m"
JAVA_OPT="${JAVA_OPT} -XX:G1ReservePercent=25"
JAVA_OPT="${JAVA_OPT} -XX:InitiatingHeapOccupancyPercent=30"
JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=4g"
1
2
3
4
5
6
2
3
4
5
6
# 客户端优化
# 生产者优化
# 发送方式选择
| 发送方式 | 吞吐量 | 可靠性 | 适用场景 |
|---|---|---|---|
| 同步发送 | 中 | 高 | 需要确认的场景 |
| 异步发送 | 高 | 中 | 高吞吐场景 |
| 单向发送 | 极高 | 低 | 日志采集等 |
| 批量发送 | 极高 | 中 | 高吞吐场景 |
# 生产者参数
DefaultMQProducer producer = new DefaultMQProducer("test-group");
producer.setNamesrvAddr("localhost:9876");
// 发送超时时间
producer.setSendMsgTimeout(3000);
// 压缩消息体阈值(超过该值压缩)
producer.setCompressMsgBodyOverHowmuch(1024 * 4);
// 最大消息大小
producer.setMaxMessageSize(1024 * 1024 * 4);
// 重试次数
producer.setRetryTimesWhenSendFailed(2);
producer.setRetryTimesWhenSendAsyncFailed(2);
// 是否在内部发送失败时重试另一台 Broker
producer.setRetryAnotherBrokerWhenNotStoreOK(false);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 批量发送
List<Message> messages = new ArrayList<>();
for (int i = 0; i < 100; i++) {
messages.add(new Message("batch-topic", "tag-a", ("msg-" + i).getBytes()));
}
// 批量发送,单批不超过 1MB
producer.send(messages);
1
2
3
4
5
6
2
3
4
5
6
# 消费者优化
# 消费线程数
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("test-group");
consumer.setNamesrvAddr("localhost:9876");
// 最小消费线程数
consumer.setConsumeThreadMin(20);
// 最大消费线程数
consumer.setConsumeThreadMax(64);
// 消费超时时间(分钟)
consumer.setConsumeTimeout(15);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 消费批量大小
// 每次消费的最大消息数
consumer.setConsumeMessageBatchMaxSize(10);
// 每次拉取的最大消息数
consumer.setPullBatchSize(32);
// 拉取间隔(毫秒)
consumer.setPullInterval(0);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 消费位点策略
// 从最后偏移量开始消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
// 从最早偏移量开始消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
// 从指定时间开始消费
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
consumer.setConsumeTimestamp("20260101000000");
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 集群优化
# 节点部署策略
| 部署策略 | 说明 | 适用场景 |
|---|---|---|
| 同机房部署 | 所有节点在同一机房 | 低延迟、高吞吐 |
| 跨机房部署 | 节点分布在不同机房 | 高可用、容灾 |
| 异构部署 | 不同配置节点混合 | 成本优化 |
# 主从复制优化
# 同步复制 vs 异步复制
| 复制方式 | 可靠性 | 性能 | 适用场景 |
|---|---|---|---|
| 同步复制 | 高 | 低 | 金融交易等强一致场景 |
| 异步复制 | 中 | 高 | 一般业务场景 |
# broker.conf
# 同步复制
brokerRole=SYNC_MASTER
# 异步复制
brokerRole=ASYNC_MASTER
1
2
3
4
5
6
2
3
4
5
6
# 刷盘策略优化
# 同步刷盘 vs 异步刷盘
| 刷盘方式 | 可靠性 | 性能 | 适用场景 |
|---|---|---|---|
| 同步刷盘 | 高 | 低 | 强一致场景 |
| 异步刷盘 | 中 | 高 | 一般业务场景 |
# broker.conf
# 同步刷盘
flushDiskType=SYNC_FLUSH
# 异步刷盘
flushDiskType=ASYNC_FLUSH
1
2
3
4
5
6
2
3
4
5
6
# Topic 队列数优化
| 场景 | 队列数建议 |
|---|---|
| 低吞吐 | 4-8 |
| 中等吞吐 | 8-16 |
| 高吞吐 | 16-32 |
| 超高吞吐 | 32-64 |
# 创建 Topic 时指定队列数
bin/mqadmin updateTopic -n localhost:9876 -c DefaultCluster -t test-topic -r 16 -w 16
1
2
2
# 监控与调优
# 性能指标
| 指标 | 健康范围 | 优化建议 |
|---|---|---|
| Broker TPS | 根据硬件配置 | 扩容或优化生产者 |
| 消费 TPS | 接近生产 TPS | 增加消费者或优化消费逻辑 |
| 消息堆积 | < 100万 | 增加消费者或优化消费逻辑 |
| 磁盘使用率 | < 75% | 扩容或清理过期消息 |
| 内存使用率 | < 80% | 增加内存或优化 JVM 参数 |
| 消费延迟 | < 1秒 | 优化消费逻辑或增加消费者 |
# 性能测试
# 使用 benchmark 工具测试
bin/benchmark.sh producer -n localhost:9876 -t test-topic -s 128 -w 16
# 参数说明
# -n: NameServer 地址
# -t: Topic 名称
# -s: 消息大小(字节)
# -w: 并发数
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 瓶颈分析
- CPU 瓶颈:发送/消费线程数不足、压缩解压、序列化
- 内存瓶颈:JVM GC 频繁、DirectBuffer 不足
- 磁盘瓶颈:刷盘方式、磁盘 I/O 不足、文件系统性能
- 网络瓶颈:跨机房部署、带宽不足、网络延迟
# 常见问题优化
# 消息堆积优化
- 增加消费者数量
- 优化消费者处理逻辑
- 增加消费线程数
- 使用批量消费
- 扩容 Broker 节点
# 发送性能优化
- 使用异步发送
- 使用批量发送
- 增加生产者数量
- 优化消息大小
- 关闭消息轨迹(如不需要)
# 消费延迟优化
- 增加消费线程数
- 优化消费逻辑
- 使用并发消费
- 扩容消费者
- 检查是否有慢消费者
# 性能优化检查清单
# 系统层面
- [ ] 文件描述符限制已调整
- [ ] 内核参数已优化
- [ ] 磁盘使用 XFS 文件系统
- [ ] 网络参数已优化
- [ ] 系统资源充足(CPU、内存、磁盘)
# RocketMQ 配置
- [ ] Broker 线程数合理设置
- [ ] 刷盘策略根据业务选择
- [ ] 复制策略根据业务选择
- [ ] 文件保留时间合理设置
- [ ] JVM 参数已优化
# 客户端优化
- [ ] 发送方式选择合适
- [ ] 消费线程数合理设置
- [ ] 批量大小合理设置
- [ ] 重试次数合理设置
- [ ] 消费位点策略合适
# 集群优化
- [ ] Topic 队列数合理设置
- [ ] 主从复制策略合适
- [ ] 刷盘策略合适
- [ ] 集群规模满足业务需求
- [ ] 节点部署策略合适
编辑页面 (opens new window)