跳转到内容

性能优化规范

性能基线、压测、瓶颈分析与优化


[Requirement] 每个核心服务必须建立性能基线,作为优化和回归的参照。基线指标包括:

指标说明采集方式
QPS每秒请求数压测 / 生产监控
响应时间P50 / P95 / P99压测 / APM
错误率失败请求占比压测 / 监控
资源使用率CPU / 内存 / 网络监控
吞吐量单位时间处理量压测

[Standard] 在 staging 环境(与 prod 同构)进行压测,建立性能基线。基线数据包含:

  • 不同并发下的 QPS、响应时间、错误率
  • 资源使用率随负载变化的曲线
  • 服务的最大承载能力(拐点)

[Standard] 性能基线必须文档化,纳入版本管理,随架构变更更新。

# user-service 性能基线
最后更新:2024-01-15
环境:staging(同 prod 配置)
 
| 并发 | QPS  | P50(ms) | P99(ms) | 错误率 | CPU  | 内存  |
|------|------|---------|---------|--------|------|-------|
| 10   | 500  | 20      | 80      | 0%     | 30%  | 40%   |
| 50   | 2000 | 25      | 120     | 0%     | 60%  | 45%   |
| 100  | 3500 | 35      | 200     | 0.1%   | 85%  | 50%   |
| 200  | 4000 | 80      | 500     | 2%     | 95%  | 60%   |
 
最大承载 QPS:3500(并发 100 时,错误率 < 0.1%)

[Standard] 每次重大变更(架构调整、核心逻辑改动)后,重新压测并与基线对比:

  • 响应时间劣化 > 20% → 需分析原因
  • 吞吐量下降 > 15% → 需分析原因
  • 错误率上升 > 0.5% → 阻塞发布

类型目的场景
基准测试建立基线单接口、固定并发
负载测试验证预期负载下的表现日常峰值流量
压力测试找到系统极限逐步加压直到崩溃
稳定性测试验证长时间运行稳定性持续 24 小时以上
容量测试确定最大容量找出吞吐量拐点

[Standard] 压测遵循以下流程:

明确目标 → 准备环境 → 准备数据 → 编写脚本 → 执行压测 → 分析结果 → 输出报告

[Standard] 根据场景选择压测工具:

工具适用场景特点
wrk / wrk2HTTP 接口轻量、高性能
k6HTTP/WS/GRPC脚本化、可扩展
JMeter复杂场景图形化、协议丰富
Locust自定义场景Python 脚本、分布式
Go-stressGo 服务原生、低开销
# 基础压测:100 并发,持续 30 秒
wrk -t4 -c100 -d30s --latency http://api.example.com/users
 
# 带请求体的 POST 压测
wrk -t4 -c100 -d30s -s post.lua http://api.example.com/orders
-- post.lua
wrk.method = "POST"
wrk.body = '{"user_id": 123, "product_id": 456}'
wrk.headers["Content-Type"] = "application/json"

[Requirement] 压测必须在 staging 环境(与 prod 同构)进行,禁止在 prod 环境直接压测(除全链路压测外)。

[Standard] 压测前必须:

  1. 通知相关团队,避免影响测试
  2. 确认压测环境数据量与 prod 同量级
  3. 确认监控已开启,可采集性能指标
  4. 确认无其他任务占用资源

[Standard] 压测数据量必须与 prod 同量级,避免数据量差异导致性能误判。

数据表prod 数据量压测数据量
users1000 万≥ 1000 万
orders5000 万≥ 5000 万
products10 万≥ 10 万
  • ❌ 在 dev 环境压测,数据量和机器配置与 prod 差异巨大。
  • ❌ 压测脚本只测一个接口,不模拟真实业务场景。
  • ❌ 压测前不通知,影响其他团队的测试工作。

[Standard] 性能瓶颈分析按以下顺序逐层排查:

客户端 → 网络 → 负载均衡 → 应用服务 → 缓存 → 数据库 → 外部依赖
层级瓶颈表现排查方法
应用层CPU 高、GC 频繁、线程阻塞Profiler(pprof / async-profiler / Arthas)
数据库层慢 SQL、连接池耗尽、锁等待慢查询日志、执行计划、锁监控
缓存层缓存击穿、命中率低缓存命中率监控、热点 Key 分析
网络层延迟高、丢包ping / mtr / tcpdump
外部依赖第三方接口慢调用耗时监控、熔断状态

Java Arthas 示例:

# 查看最耗时的方法
trace com.example.UserService getUserById
 
# 查看方法调用栈
stack com.example.UserService getUserById
 
# 监控方法执行耗时
monitor -c 5 com.example.UserService getUserById

Go pprof 示例:

# 采集 CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
 
# 采集内存 profile
go tool pprof http://localhost:6060/debug/pprof/heap
 
# 火焰图
go-torch -u http://localhost:6060 -t 30

Python py-spy 示例:

# 实时查看函数调用
py-spy top --pid 12345
 
# 生成火焰图
py-spy record -o profile.svg --pid 12345

[Standard] 慢查询排查步骤:

# 1. 开启慢查询日志,设置阈值 100ms
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 0.1;
 
# 2. 查看慢查询
SELECT * FROM mysql.slow_log ORDER BY query_time DESC LIMIT 10;
 
# 3. 分析执行计划
EXPLAIN SELECT * FROM orders WHERE user_id = 123;

[Caution] 禁止在生产环境对大表执行无索引的查询或全表扫描。详细规则见 慢SQL治理规范。

[Standard] 瓶颈定位遵循”先定位再优化”原则:

  1. 先通过监控和日志缩小瓶颈范围
  2. 再用 Profiler 精确定位瓶颈代码
  3. 最后针对性优化,避免盲目优化

[Caution] 禁止在未定位瓶颈前盲目优化,可能优化了非瓶颈,浪费精力且无效果。


优化方向具体措施预期收益
算法优化降低时间复杂度(O(n²) → O(n log n))高
并发优化异步处理、线程池调优、协程中-高
缓存优化本地缓存、分布式缓存、缓存预热高
批处理批量查询、批量写入中
连接池数据库/HTTP 连接池调优中
对象复用避免频繁创建对象、对象池中
序列化优化切换高效序列化(Protobuf / JSON 优化)中
优化方向具体措施预期收益
索引优化合理添加索引、覆盖索引、联合索引高
SQL 优化避免 SELECT *、减少 JOIN、分页优化高
分库分表读写分离、水平/垂直拆分高
连接池合理配置连接池大小中
读写分离读操作走从库中
数据归档冷数据归档,减少热数据量中

[Standard] 缓存策略选择:

场景策略说明
读多写少Cache-Aside先读缓存,未命中读 DB 再写缓存
写多读少Write-Through写时同步更新缓存
高并发写Write-Behind异步写 DB,削峰填谷

[Caution] 缓存三大问题必须有对应方案:

问题解决方案
缓存穿透布隆过滤器 / 缓存空值
缓存击穿互斥锁 / 永不过期 + 异步更新
缓存雪崩过期时间加随机值 / 多级缓存
优化方向具体措施
服务拆分单体拆微服务,独立扩容
读写分离读操作走只读副本
消息队列异步解耦、削峰填谷
CDN静态资源边缘加速
负载均衡多实例水平扩展
就近访问多机房部署、边缘计算

[Requirement] 任何优化措施上线前,必须在 staging 环境压测验证,确认性能提升且无副作用。

[Standard] 优化验证对比模板:

指标优化前优化后提升
QPS20005000+150%
P99 延迟500ms120ms-76%
CPU 使用率85%45%-47%
错误率1%0%-100%
  • ❌ 过早优化:在未确认瓶颈前就优化代码。
  • ❌ 过度优化:为了 1% 的性能提升牺牲可读性和可维护性。
  • ❌ 优化后不压测验证,直接上线。

[Requirement] 生产环境必须实时监控以下性能指标,设置告警阈值:

指标告警阈值级别
P99 响应时间> 2s 持续 5 分钟P1
P95 响应时间> 1s 持续 5 分钟P2
QPS 突降较基线下降 > 30%P1
错误率> 1%P0
CPU 使用率> 85% 持续 5 分钟P1
内存使用率> 90% 持续 5 分钟P1
GC 停顿> 500ms 持续 5 分钟P2

[Standard] 超过阈值的请求(默认 1s)必须记录详细日志,包含:

  • 请求参数(脱敏后)
  • 各阶段耗时(路由、业务、DB、缓存、外部调用)
  • trace_id(可跳转链路追踪)
{
  "trace_id": "abc123",
  "slow_request": true,
  "cost_ms": 1500,
  "breakdown": {
    "route": 5,
    "business": 200,
    "db_query": 800,
    "redis": 50,
    "external_api": 445
  },
  "params": { "user_id": 123 }
}

[Standard] 监控服务容量水位,提前预警:

指标预警阈值动作
服务负载达到最大容量 70%预警,准备扩容
服务负载达到最大容量 85%自动扩容
数据库连接达到连接池 80%预警
磁盘使用率> 80%预警,清理或扩容

[Standard] 核心业务流程必须有全链路监控,可追踪请求从入口到所有依赖的完整耗时。

客户端 → LB → Nginx → 网关 → 业务服务 → DB
└→ Redis
└→ MQ
└→ 外部 API

[Suggestion] 使用 APM 工具(SkyWalking / Datadog / New Relic)实现全链路性能监控。

  • ❌ 只监控错误率,不监控响应时间,慢请求无人感知。
  • ❌ 没有容量水位监控,流量突增时服务被打垮才发现。
  • ❌ 慢请求只记录总耗时,不记录各阶段耗时,无法定位瓶颈。