一、压测准备

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%

发现问题

  1. Redis连接池耗尽,出现超时
  2. 部分节点CPU使用率达到85%
  3. 响应时间P95超过预期

3.3 第三轮压测(并发5000)

压测结果

TPS: 8.2万
平均响应时间: 58ms
P95响应时间: 120ms
错误率: 2.3%
Redis QPS: 16万

发现问题

  1. Redis成为瓶颈:主备实例64G内存无法支撑
  2. 网络带宽不足:ELB带宽400M接近饱和
  3. 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 关键优化点

架构层面

  1. Redis单实例→集群,解决读写瓶颈
  2. ELB带宽扩容,消除网络限制
  3. 集群节点数量合理配置

应用层面

  1. JVM参数精细化调优
  2. 连接池合理配置
  3. 缓存预热减少冷启动影响
  4. 异步化非核心逻辑

监控层面

  1. 全链路监控覆盖
  2. 关键指标实时告警
  3. 压测数据持续收集

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 持续改进

  • 定期进行压测验证
  • 优化高频调用链路
  • 代码层面性能优化
  • 架构持续演进