10万TPS级高并发系统——性能压测与优化
一、压测准备
1.1 系统背景
消息发送管控平台需要支持10万TPS的接口调用,要求单次请求处理耗时在50ms以内。系统采用集群化部署,通过弹性负载均衡实现高可用和性能扩展。
核心技术指标:
- 目标TPS:10万
- 响应时间:≤50ms
- 日发送量:30亿条
- 平均发送速度:3.47万条/秒
1.2 压测环境
| 组件 | 规格配置 | 数量 |
|---|---|---|
| 管控API服务 | 16核/32GB/500G高IO | 15节点 |
| Redis集群 | 256G/32分片 | 32实例 |
| MySQL数据库 | 16核/32GB/1TB超高IO | 主从 |
| 负载均衡器 | 中型II/500M带宽 | 1台 |
| 压测客户端 | 8核/16GB | 3台 |
1.3 压测工具选型
选用 JMeter 作为压测工具:
- 支持高并发场景
- 可视化报表
- 分布式压测
- 插件丰富
二、压测方案设计
2.1 压测场景
场景一:基础功能压测
- 并发用户数:1000 → 3000 → 5000
- 持续时间:每阶段10分钟
- 目标:验证基础性能
场景二:峰值压测
- 并发用户数:5000
- 持续时间:30分钟
- 目标:验证10万TPS目标
场景三:稳定性压测
- 并发用户数:4000
- 持续时间:2小时
- 目标:验证系统稳定性
2.2 监控指标
应用层指标:
- TPS(每秒事务数)
- 响应时间(平均/P95/P99)
- 错误率
- 并发连接数
系统层指标:
- CPU使用率
- 内存使用率
- 网络带宽
- 磁盘IO
中间件指标:
- Redis QPS
- MySQL连接数
- 负载均衡器吞吐量
三、压测过程与问题
3.1 第一轮压测(并发1000)
压测结果:
TPS: 2.8万
平均响应时间: 35ms
P95响应时间: 48ms
错误率: 0%
CPU使用率: 45%
结论:基础性能正常,继续提升并发
3.2 第二轮压测(并发3000)
压测结果:
TPS: 6.5万
平均响应时间: 45ms
P95响应时间: 78ms
错误率: 0.1%
发现问题:
- Redis连接池耗尽,出现超时
- 部分节点CPU使用率达到85%
- 响应时间P95超过预期
3.3 第三轮压测(并发5000)
压测结果:
TPS: 8.2万
平均响应时间: 58ms
P95响应时间: 120ms
错误率: 2.3%
Redis QPS: 16万
发现问题:
- Redis成为瓶颈:主备实例64G内存无法支撑
- 网络带宽不足:ELB带宽400M接近饱和
- GC频繁:Young GC每秒触发2-3次
四、性能优化实践
4.1 Redis集群升级
问题分析:
- 每次请求至少访问2次Redis
- 10万TPS下Redis QPS达到20万
- 单实例无法支撑高并发读写
优化方案:
- 升级为Redis集群(32分片/256G)
- 水平扩展读写能力
- 数据分片降低单节点压力
优化效果:
Redis QPS支持: 20万+ → 100万+
Redis响应时间: 5-8ms → 1-3ms
4.2 负载均衡器优化
问题分析:
- 中型II默认带宽400M
- 10万TPS下带宽需求超过500M
优化方案:
- 升级带宽至600M
- 调整负载均衡算法为加权轮询
- 启用会话保持
优化效果:
带宽瓶颈消除
请求分发更均衡
4.3 JVM参数调优
问题分析:
- 堆内存16G配置不合理
- Young GC频繁触发
- Full GC偶发
优化方案:
-Xms24G -Xmx24G
-Xmn12G
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50
-XX:G1ReservePercent=10
-XX:InitiatingHeapOccupancyPercent=45
优化效果:
Young GC频率: 2-3次/秒 → 0.5次/秒
GC暂停时间: 20-30ms → 10-15ms
Full GC: 偶发 → 未出现
4.4 连接池优化
Redis连接池配置:
jedis:
pool:
max-active: 500 # 最大连接数
max-idle: 300 # 最大空闲连接
min-idle: 100 # 最小空闲连接
max-wait: 3000 # 最大等待时间(ms)
MySQL连接池配置:
datasource:
hikari:
maximum-pool-size: 100
minimum-idle: 50
connection-timeout: 5000
idle-timeout: 600000
4.5 应用层优化
1. 缓存预热
@PostConstruct
public void preloadCache() {
// 预加载热点数据
List<Keyword> keywords = keywordService.getAllKeywords();
keywords.forEach(k -> redisCache.set(k.getId(), k));
}
2. 异步处理
// 非核心逻辑异步化
@Async("taskExecutor")
public void recordAuditLog(AuditLog log) {
auditLogRepository.save(log);
}
3. 批量操作
// Redis批量获取
List<String> keys = buildKeys(ids);
List<Object> values = redisTemplate.opsForValue().multiGet(keys);
五、优化后压测结果
5.1 峰值压测(并发5000)
压测数据:
测试时长: 30分钟
总请求数: 1.8亿次
TPS: 10.2万
平均响应时间: 42ms
P95响应时间: 58ms
P99响应时间: 75ms
错误率: 0.02%
资源使用情况:
API服务CPU: 65-75%
API服务内存: 18-20G
Redis QPS: 20.5万
Redis内存: 45%
MySQL连接数: 平均80
ELB带宽: 480-520M
5.2 稳定性压测(并发4000)
压测数据:
测试时长: 2小时
总请求数: 28.8亿次
TPS: 8万
平均响应时间: 38ms
P95响应时间: 52ms
错误率: 0.01%
稳定性指标:
- 无内存泄漏
- GC稳定
- 无连接池耗尽
- 响应时间波动<5ms
六、性能调优总结
6.1 优化效果对比
| 指标 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| TPS | 8.2万 | 10.2万 | +24% |
| 平均响应时间 | 58ms | 42ms | -27% |
| P95响应时间 | 120ms | 58ms | -52% |
| 错误率 | 2.3% | 0.02% | -99% |
| GC频率 | 2-3次/秒 | 0.5次/秒 | -75% |
6.2 关键优化点
架构层面:
- Redis单实例→集群,解决读写瓶颈
- ELB带宽扩容,消除网络限制
- 集群节点数量合理配置
应用层面:
- JVM参数精细化调优
- 连接池合理配置
- 缓存预热减少冷启动影响
- 异步化非核心逻辑
监控层面:
- 全链路监控覆盖
- 关键指标实时告警
- 压测数据持续收集
6.3 压测经验
1. 渐进式压测
- 从低并发开始逐步提升
- 每个阶段充分验证
- 及时发现性能瓶颈
2. 全面监控
- 应用、系统、中间件指标齐全
- 实时监控压测过程
- 保留压测数据用于分析
3. 问题定位
- 结合日志、监控定位问题
- 使用性能分析工具(JProfiler等)
- 必要时进行线程dump分析
4. 持续优化
- 压测→优化→再压测
- 建立性能基线
- 定期回归测试
七、生产环境表现
7.1 真实流量验证
日常运行数据(上线后一个月):
日均请求量: 28亿次
峰值TPS: 9.8万
平均响应时间: 35ms
P99响应时间: 68ms
可用性: 99.99%
7.2 大促期间表现
618活动期间:
峰值TPS: 10.5万
持续时长: 4小时
平均响应时间: 43ms
错误率: 0.01%
系统稳定运行
八、最佳实践建议
8.1 容量规划
- 按峰值TPS的1.5-2倍规划容量
- 预留30%性能buffer
- 关键组件支持水平扩展
8.2 监控告警
- TPS超过8万时告警
- 响应时间P95>60ms告警
- 错误率>0.1%告警
- 资源使用率>80%告警
8.3 应急预案
- 限流降级策略
- 快速扩容方案
- 数据库读写分离
- 核心功能降级开关
8.4 持续改进
- 定期进行压测验证
- 优化高频调用链路
- 代码层面性能优化
- 架构持续演进
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 逐光の博客!
评论




