第 242 章:综合调优实战
学习目标
- 综合应用前序调优方法
- 性能测试方法
- 容量规划
- 性能回归
一、综合调优方法论
二、性能测试
2.1 工具
| 工具 | 特点 |
|---|---|
| JMeter | GUI + 分布式 |
| wrk | 轻量高并发 |
| gatling | Scala DSL |
| Locust | Python,易扩展 |
| k6 | JS,云原生 |
2.2 WRK 示例
bash
# 12 线程, 400 连接, 30 秒
wrk -t12 -c400 -d30s \
-H "Authorization: Bearer xxx" \
--script=POST.lua \
http://localhost:8080/api/orders2.3 JMeter 测试计划
xml
<ThreadGroup>
<numThreads>100</numThreads>
<rampTime>30</rampTime>
<duration>300</duration>
<ConstantThroughputTimer>
<throughput>1000</throughput>
</ConstantThroughputTimer>
<HTTPSampler>
<domain>api.example.com</domain>
<path>/api/orders</path>
<method>GET</method>
</HTTPSampler>
</ThreadGroup>2.4 关键指标
Latency:
- 平均(P50)
- 90%
- 95%
- 99%
- 最大
Throughput:
- QPS
- TPS
Error Rate:
- 成功率 / 失败率
Resource:
- CPU
- Memory
- GC 频率
- DB 连接2.5 全链路压测
yaml
思想: 在生产环境,用压测流量标记
- 染色: header X-Test-Flag = 1
- 测试数据入影子库
- 不污染线上
工具:
- 阿里云 PTS
- 京东 ForceBot
- 美团 Leak
- 自建方案三、性能瓶颈案例
3.1 案例 1:订单详情接口慢
| 阶段 | 优化 |
|---|---|
| 1 | 加缓存(JVM + Redis),命中率 95% |
| 2 | DB 索引优化(联合覆盖索引) |
| 3 | 异步合并查询(订单 + 商品 + 用户) |
| 4 | DB 读写分离 |
| 5 | ES 替代 DB 搜索 |
3.2 案例 2:整点秒杀雪崩
yaml
问题: 整点秒杀,大量缓存同时过期,DB 挂
方案:
- 1: 缓存预热(启动时加载)
- 2: 过期时间随机化(60-90 秒)
- 3: Sentinel 限流保护 DB
- 4: DB 读写分离
- 5: 库存本地缓存 + 校验3.3 案例 3:全链路 GC 频繁
yaml
症状: 1 分钟内 Full GC 5 次,停顿 1 秒
原因:
- 查询返回 100 万数据(大对象)
- 内存不够
解决:
- 分页查,每次 1000
- 升堆
- 用游标
- 流式消费(Stream)四、性能优化清单
4.1 应用层
yaml
✅ JVM GC 调优
✅ 线程池参数合理
✅ 对象复用(StringBuilder / ThreadLocal)
✅ 避免大事务
✅ 锁粒度细化
✅ 异步处理耗时
✅ 缓存命中率 > 90%4.2 数据层
yaml
✅ 索引覆盖所有热点查询
✅ 慢查询定期 review
✅ SQL 避免 SELECT *
✅ 读写分离
✅ 分库分表(数据量大)
✅ Connection Pool 合理4.3 缓存层
yaml
✅ 多级缓存
✅ 热点数据预热
✅ 解决雪崩/穿透/击穿
✅ Redis 大 key 拆分
✅ Pipeline 批量操作
✅ 内存淘汰策略4.4 网络层
yaml
✅ HTTP/2 多路复用
✅ Keep-Alive
✅ 启用压缩
✅ 启用 HTTP 缓存头
✅ CDN 加速
✅ 合理超时4.5 架构层
yaml
✅ MQ 削峰
✅ 异步化
✅ 限流保护
✅ 熔断容错
✅ 灰度发布
✅ 多级容灾五、性能优化效果评估
5.1 性能指标树
5.2 优化前后对比
| 指标 | 优化前 | 优化后 | 改善 |
|---|---|---|---|
| QPS | 1000 | 5000 | 5x |
| P99 | 800 ms | 200 ms | -75% |
| CPU | 80% | 50% | -38% |
| 错误率 | 0.5% | 0.01% | -98% |
| GC 频率 | 30/min | 5/min | -83% |
5.3 指标统计
java
// 关键指标 Micrometer
public class PerfMetrics {
@Autowired
private MeterRegistry registry;
public void record(String op, long startNs, boolean success) {
Timer timer = Timer.builder("ops.duration")
.tag("op", op)
.tag("status", success ? "ok" : "fail")
.register(registry);
timer.record(Duration.ofNanos(System.nanoTime() - startNs));
}
}六、性能验收
6.1 验收场景
yaml
场景:
- 正常工作: 1 倍峰值
- 峰值压力: 历史峰值 1.5 倍
- 极限压力: 5 倍正常
- 持续运行: 24 小时 8 小时负载6.2 验收标准
| 项目 | 目标 |
|---|---|
| 峰值 QPS | >= 目标 QPS |
| P99 延迟 | < 业务要求(通常 200-500 ms) |
| 错误率 | < 0.1% |
| CPU | < 75% |
| 内存 | < 80% |
| GC 暂停 | < 200 ms(单次) |
| 持续运行 | < 内存泄漏 |
6.3 持续压测
yaml
用 Jenkins + JMeter 集成:
- nightly 跑全链路压测
- 数据入库报告
- 异常告警七、容量规划
7.1 维度
yaml
数据量:
- 当前数据
- 年增长率
- 表拆分阈值
流量:
- 当前 QPS
- 峰值 QPS
- 业务预期增长
计算资源:
- CPU 核
- 内存
- 磁盘 IO
存储:
- 数据库
- 文件 / OSS
- 备份7.2 计算示例
业务目标:
- DAU 100 万
- 每用户 10 请求/天
- 峰值占 5% 流量
QPS = 100万 × 10 / (86400) / 0.05 ≈ 232
业务通常按 3x 考虑峰值:QPS 700
单机性能(QPS): 200(普通 8 核)
冗余: 1.5 倍
应用机器数 = 700 / 200 / 0.6 ≈ 6 台7.3 资源规划
yaml
CPU: 8 核 * 6 台 = 48 核
内存: 16G * 6 = 96 GB (堆 60% = 9.6G / JVM)
DB: 32 核 + 64G + SSD
Redis: 32G 主从
消息: 6 个分区,Kafka 3 节点八、性能文化
8.1 性能预算
yaml
每个页面:
- JS: < 200 KB(压缩)
- 首屏: < 1.5 秒
- 可交互: < 3 秒
每个接口:
- P99: < 200ms
- 网络往返: < 5 次8.2 性能卡(Lighthouse)
yaml
综合分:
- Performance
- Accessibility
- Best Practices
- SEO
- PWA集成到 CI,得分低于 80 不通过。
8.3 性能 Deck 评审
yaml
每次大改,做:
- 数据库变更评审
- 缓存策略评估
- 性能影响评估
- 容量评估九、典型场景的最佳实践
9.1 读多写少(商品、详情页)
yaml
✅ 多级缓存(JVM + Redis)
✅ CDN 加速静态资源
✅ 动静分离
✅ 长连接 keep-alive
✅ 接口合并(订单 + 商品列表)9.2 写多读少(日志、埋点)
yaml
✅ Kafka 削峰
✅ 批量写入
✅ 异步落库
✅ 分区策略
✅ 压缩传输9.3 OLAP 分析(BI、报表)
yaml
✅ ClickHouse / Doris / StarRocks
✅ 物化视图
✅ 分区 + 排序键
✅ 列式存储
✅ 异步刷新9.4 实时(推荐、监控)
yaml
✅ Flink
✅ Redis Cluster
✅ 状态后端: RocksDB
✅ 背压机制
✅ Checkpoint 配置十、读后感(回到原点)
yaml
1. 不要过早优化
- 八二原则
- 找到瓶颈再改
2. 先测后改
- 基线对比
- 量化收益
3. 全面思考
- 应用层 + 数据层 + 架构层
- 兼顾一致性与可用性
4. 持续监控
- 优化方案要在监控下工作
- 异常及时止损
5. 性能是工程
- 测量、分析、修改、验证
- 反复迭代十一、本章小结
| 主题 | 关键 |
|---|---|
| 方法 | 测 + 找 + 改 + 验 |
| 场景 | 读多 / 写多 / OLAP / 实时 |
| 验收 | P99 / 错误率 / GC |
| 容量 | 业务增长 + 冗余 |
动手练习
- 用 JMeter 跑完整场景压测,记录基线
- 用火焰图找 3 个最大热点,优化后再测
- 写一个完整的容量规划报告
- 持续运行 24 小时压测,观察资源泄漏
下一章:第 243 章:架构总结与面试