压测结果不稳定的 5 大原因
- 网络抖动 --- 压测机与被测服务跨 AZ/跨机房,RTT 波动大,TP99 出现毛刺;解法:同机房同网段,延迟 < 1ms
- JVM 预热不充分 --- JIT 编译器需 5-30 分钟才能把热点代码编译成机器码,预热前后性能差 3-5 倍;解法:压测前先跑 10-15 分钟低负载预热
- 连接池打满 --- HikariCP 默认 max-pool-size=10,高并发下连接耗尽,后续请求排队;解法:
maximum-pool-size=50,压测前按峰值评估调大 - 缓存冷启动 --- Redis/本地缓存为空时所有请求打到 DB,首次压测 RT 500ms vs 预热后 100ms,差 5 倍;解法:压测前跑热点数据预热缓存
- GC 抖动 --- 高并发对象分配速率高,频繁 Stop The World,RT 曲线出现规律尖峰;解法:
-XX:MaxGCPauseMillis=100调优 G1
让结果稳定的 5 个关键做法
- 三遍取中位数基线法 --- 单次压测无意义,取三轮中位数再取中位数(如:205ms / 208ms / 203ms → 最终 205ms);偏差 > 10% 阻断发布
- 专有压测环境隔离 --- 独立集群独立数据库,禁止与测试/开发环境混用,避免其他业务干扰
- 监控先行,压测前健康检查 --- CPU < 30%、JVM 堆 < 60%、DB 连接空闲、Redis 正常;确认干净后再开始正式压测
- 数据与生产等量级 --- 预置足够账户/库存(如 10 万用户账户),避免数据量不足导致锁竞争和索引效率失真
- 四大指标看 TP99 --- 不只看平均值,TP50 < 200ms / TP90 < 500ms / TP99 < 1000ms / Error% < 0.1%,四指标全部达标才算通过
1. JMeter 分布式压测架构
架构:Controller + Slave(多台机器协同发压)
JMeter Controller(控制台/报告生成,Port 1099)
│ RMI
┌────┼────────────┐
│ │ │
Slave1 Slave2 Slave3
800线程 800线程 800线程
└─────┬────────────┘
│ 共同发压
被测服务(金融核心系统)
为什么单机 ~1000 并发封顶?
单台 JMeter 进程稳定并发约 800-1000 线程,超过后:
- JVM 堆内存暴涨(每线程 1MB 栈空间)
- RMI 通信开销成倍增加
- JMeter 自身先 OOM / CPU 打满,成为瓶颈而非被测服务
金融项目推荐规格: 3-5 台 Slave × 800 线程 = 2400-4000 总并发,覆盖绝大多数场景
2. JMeter vs wrk / Locust / k6 / Gatling
| 工具 | 语言 | 协议 | 上手 | 报告 | 金融项目评价 |
|---|---|---|---|---|---|
| JMeter | Java | HTTP/Dubbo(插件)/gRPC(插件) | 中 | 基础 | 全协议,体系成熟,GUI 性能差 |
| wrk | C | 仅 HTTP | 低 | 极弱 | 性能极高,适合 HTTP 基准测试 |
| Locust | Python | HTTP/gRPC | 中 | 中 | 分布式强,GIL 限制单机性能 |
| k6 | Go | HTTP/gRPC/GraphQL | 低 | 强 | JS 脚本,DevOps 友好 |
| Gatling | Scala | HTTP/Dubbo | 中 | 最强 | 报告最专业,Scala 门槛高 |
金融项目首选:JMeter(HTTP 主链路) + wrk(HTTP 基准线) + SkyWalking(链路分析)
3. JMeter + SkyWalking 联动压测
核心分工:JMeter 发请求记 RT,SkyWalking 定位根因
JMeter 发压 → Java Agent 自动埋点 → SkyWalking OAP → UI 实时拓扑/链路
实操四步:
- 被测服务挂载 SkyWalking Agent(
-javaagent) - JMeter 压测请求加标签 Header:
X-Biz-Scene=load-test - SkyWalking UI 实时看拓扑图(哪个节点变红)+ Trace 筛选 load-test
- SkyWalking 链路详情直接定位慢节点(如:bank-gateway 1800ms,MySQL 50ms)
黄金法则: JMeter 告诉你"慢了",SkyWalking 告诉你"哪里慢了、为什么慢"