Skip to content

07 · 服务端性能与容量:定位瓶颈的方法 ​

性能优化的第一步不是"快",是"找到慢在哪"。本篇讲后端定位瓶颈的通用方法论:从经验直觉到实测。

速览卡 ​

项内容
一句话定位后端性能问题怎么定位:先分层测,再对症下药
核心内容性能优化的正确顺序、连接池/线程模型、数据库慢查询、缓存、压测、容量估算
读完能回答服务变慢先查哪?数据库慢查询怎么定位?压测怎么看结果?
相关板块C10 · 数据建模 | C13 · 缓存与 Redis | C08 · 可观测性

一、优化的正确顺序 ​

先测后优化,一次只改一个变量。 90% 的"性能差"不是语言慢,而是:

常见瓶颈优先级
数据库慢查询 / 缺索引最先查
N+1 查询高
无缓存的热点查询高
连接池耗尽中
阻塞调用卡事件循环中
语言本身最低(几乎不是瓶颈)

铁律:没有压测/数据支撑的"优化"是玄学。先量化,再动手。


二、连接池与线程模型 ​

2.1 连接池耗尽 ​

症状:请求超时、日志出现"获取连接超时"。

排查:连接池大小 vs 数据库 max_connections,是否泄漏(连接未归还)。

python
# 连接池参数(SQLAlchemy)
create_engine(url, pool_size=10, max_overflow=20, pool_timeout=30)

2.2 线程/进程模型 ​

运行时模型注意事项
Node单线程事件循环阻塞调用全卡
Python (asyncio)事件循环 + 线程池async 里别调阻塞库
Gogoroutine量大但省资源

对 FastAPI:async def 里调阻塞库 = 卡死(见 C09)。普通 def 路由自动进线程池。


三、数据库慢查询:第一排查对象 ​

sql
-- 1. 看执行计划:走没走索引
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 42;

-- 2. 查慢查询日志
-- PostgreSQL: log_min_duration_statement / pg_stat_statements
现象常见原因解法
全表扫描缺索引 / 写法让索引失效加索引、改写法
N+1循环里逐条查批量查询(IN / join)
排序慢大结果集无索引排序字段加索引
锁等待事务太长缩短事务、控制并发

N+1:查了 100 个用户,每个又查一次订单 = 101 次查询。改成一次 WHERE user_id IN (...)。


四、缓存:性能的第二板斧 ​

先查库再谈缓存。热点读 + 一致性可接受 → 加 缓存。顺序:

text
① 加索引 / 优化 SQL   → ② 加缓存(先防穿透/击穿/雪崩) → ③ 再谈架构层

五、压测:用数据说话 ​

5.1 工具 ​

工具用途
wrk / ab简单 HTTP 压测
k6场景化压测、门槛低
LocustPython、分布式压测

5.2 看什么指标 ​

指标含义关注
QPS每秒请求数上限
RT(P95/P99)响应时间分位尾巴有多长
错误率5xx/超时占比必须低
资源CPU/内存/连接谁先到瓶颈
bash
wrk -t4 -c100 -d30s http://localhost:8000/items

重点看 P99 而不是平均值:平均好看、尾巴很长的系统线上体验很差。


六、容量估算 ​

text
需要 QPS = 峰值并发 × 单请求耗时 / 目标利用率
实例数   = 需要 QPS / 单实例压测 QPS

给"峰值 × 1.5 余量",别按平均算。压测出来的单实例 QPS 是估算的基础,不是拍脑袋。


自检清单 ​

  • [ ] 能按"先数据库 → 再缓存 → 再架构"的顺序排查
  • [ ] 会用 EXPLAIN ANALYZE 定位慢查询,识别 N+1
  • [ ] 知道连接池耗尽的症状与排查
  • [ ] 会用 wrk/k6 压测,并看 QPS/P99/错误率
  • [ ] 会做简单的容量估算

常见误区 ​

  • 误区:性能差先换语言/框架。 绝大多数瓶颈在数据库和 IO,不是语言。
  • 误区:看平均响应时间。 要看 P99,尾巴才是真实体验。
  • 误区:加缓存一定变快。 命中率低、一致性差的缓存是负优化。
  • 误区:没压测就"优化"。 没有数据支撑的优化是玄学。

动手练习 ​

练习 A:定位一次慢查询 ​

构造一个无索引的查询,用 EXPLAIN ANALYZE 看到全表扫描,加索引后再对比。

练习 B:修 N+1 ​

写一个循环查订单的接口,改成批量查询,压测对比 QPS 和 P99。

练习 C:压测报告 ​

对你的服务做一次 wrk 压测,记录 QPS、P99、错误率,写一页容量估算。


相关文档 ​

本区 ​

其他域 ​