1. 性能基准与目标设定:定义性能指标、设定SLA、搭建压测环境
做性能调优,第一件事不是撸起袖子改代码。
你得先搞清楚三件事:测什么、目标多少、怎么测。我见过太多团队,上来就压测,跑出一堆数字,然后面面相觑——这算好还是不好?说白了,没有基准和目标,调优就是瞎忙活。
1.1 核心性能指标:你到底该看什么
性能指标很多,但真正关键的,其实就几个。我个人习惯把它们分成三类:吞吐、延迟、错误。
1.1.1 QPS / TPS —— 吞吐量
QPS(Queries Per Second) 和 TPS(Transactions Per Second),衡量的是系统每秒能处理多少请求或事务。对于API服务,我们通常说QPS。
举个例子:你的接口1秒能扛住1000次调用,那QPS就是1000。注意,这里有个坑——QPS不是越高越好,它必须和延迟一起看。我曾经遇到一个项目,压测显示QPS冲到5000,但TP99已经飙到8秒了。这种高QPS毫无意义,用户早跑了。
1.1.2 TP99 / TP999 —— 尾部延迟
平均延迟(Avg Latency)是个骗人的东西。你想想看,100个请求里,99个1ms,1个10s,平均延迟才100ms左右,看起来很美。但那个倒霉的用户,等10秒才拿到结果。
TP99 的意思是:把100个请求的延迟从小到大排序,第99个的延迟值。它告诉你,99%的请求都能在多少毫秒内完成。TP999同理,更严格。
我的经验法则:
- TP99 一般控制在平均延迟的 3-5 倍以内
- 如果 TP99 超过平均延迟的 10 倍,说明有严重的长尾问题
- TP999 超过 1 秒的接口,必须优化
1.1.3 延迟(Latency)
延迟就是单个请求从发出到收到响应的时间。通常关注 P50(中位数)、P90、P99 三个分位值。
我习惯把延迟拆成两部分看:
- 网络延迟:客户端到服务端的传输时间
- 服务延迟:服务端实际处理时间(这才是我们优化的重点)
1.1.4 错误率(Error Rate)
压测时,错误率必须 严格控制在 0.1% 以下。超过 1% 的压测结果,基本可以作废了——因为系统已经处于不稳定状态。
避坑指南: 我曾经压测一个订单服务,QPS 和 TP99 都很好看,但没注意错误率。上线后,大量订单创建失败,用户投诉炸了。后来一查,压测时错误率已经到 3% 了,但被平均数据掩盖了。从此以后,我压测报告的第一行永远是错误率。
1.2 设定SLA目标:别拍脑袋,要讲道理
SLA(Service Level Agreement)不是随便写个数字。你得根据业务场景、用户容忍度、成本来定。
1.2.1 常见的SLA参考值
| 业务场景 | 推荐 TP99 | 推荐 QPS 目标 | 错误率上限 |
|---|---|---|---|
| 用户登录/认证 | < 200ms | 按峰值 x 1.5 | 0.01% |
| 商品详情页 | < 500ms | 按峰值 x 2 | 0.1% |
| 订单提交 | < 1s | 按峰值 x 3 | 0.01% |
| 报表/大数据查询 | < 5s | 按峰值 x 1.2 | 0.5% |
注意,这里的「峰值 x N」是指 预留一定的余量。我一般按峰值流量的 1.5 到 2 倍来设定目标。为什么?因为压测环境和线上环境总有差异,留点余量心里踏实。
1.2.2 设定SLA的步骤
- 收集历史数据:从监控系统拉取过去1-3个月的流量峰值、平均延迟
- 确定业务容忍度:和产品、运营聊,用户能等多久?超时多少会投诉?
- 设定初步目标:比如 TP99 500ms,QPS 2000
- 压测验证:跑一轮压测,看能不能达到
- 调整并固化:达不到就优化,或者调整目标(但别轻易降低标准)
小技巧: 设定SLA时,可以分 核心接口 和 非核心接口。核心接口(如登录、支付)的SLA要严格,非核心接口(如历史记录查询)可以适当放宽。这样既能保证用户体验,又不会把成本全堆在优化上。
1.3 搭建压测环境:选对工具,事半功倍
压测环境不是随便找台机器跑一下就行。我见过有人用笔记本压测线上服务,结果网络延迟就把数据搞废了。
1.3.1 环境要求
- 压测机:和线上服务在同一内网,避免公网波动
- 压测机配置:CPU 至少 4 核,内存 8G 以上(不然压测工具自己先崩了)
- 目标服务:独立部署,不要和压测机混用资源
- 监控:压测期间,同时监控服务端的 CPU、内存、IO、网络
1.3.2 工具选择:wrk vs JMeter
| 对比项 | wrk | JMeter |
|---|---|---|
| 定位 | 轻量级命令行工具 | 全功能图形化压测平台 |
| 协议支持 | HTTP/HTTPS | HTTP、TCP、JDBC、MQ 等 |
| 学习成本 | 低(5分钟上手) | 中(需要熟悉GUI) |
| 性能 | 极高(基于C + epoll) | 中等(Java,线程模型) |
| 分布式压测 | 需自己写脚本 | 原生支持 |
| 适用场景 | 快速验证、单接口压测 | 复杂场景、多接口链路压测 |
我个人习惯:日常开发用 wrk,几秒钟就能跑一轮,快速验证改动效果。正式压测用 JMeter,可以录制脚本、设置断言、生成详细报告。
1.3.3 wrk 实战:5分钟跑起来
安装很简单,Mac 上 brew install wrk,Linux 上编译也很方便。
# 基本用法:压测 30 秒,12 个线程,400 个并发连接
wrk -t12 -c400 -d30s http://your-api:8080/hello
# 输出示例:
# Running 30s test @ http://your-api:8080/hello
# 12 threads and 400 connections
# Thread Stats Avg Stdev Max +/- Stdev
# Latency 45.67ms 12.34ms 345.67ms 87.50%
# Req/Sec 723.45 89.12 1.23k 75.00%
# 259,842 requests in 30.00s, 38.97MB read
# Requests/sec: 8661.40
# Transfer/sec: 1.30MB
看到 Requests/sec: 8661.40 了吗?这就是 QPS。Latency 那一行,Avg 是平均延迟,但没有 TP99。别急,加个参数:
# 打印详细的延迟分布
wrk -t12 -c400 -d30s --latency http://your-api:8080/hello
# 输出中会多出:
# Latency Distribution (HdrHistogram - Recorded Latency)
# 50.000% 42.00ms
# 75.000% 56.00ms
# 90.000% 72.00ms
# 99.000% 112.00ms
# 99.900% 256.00ms
# 99.990% 340.00ms
嗯,TP99 是 112ms,TP999 是 256ms。这个接口的延迟分布一目了然。
1.3.4 JMeter 实战:复杂场景必备
JMeter 我主要用来做 多接口链路压测。比如一个下单流程:登录 → 查询商品 → 创建订单 → 支付。每个接口的依赖关系、参数传递,JMeter 都能处理。
基本步骤:
- 创建线程组(设置并发数、循环次数)
- 添加 HTTP 请求默认值(统一域名、端口)
- 添加 HTTP 请求(每个接口一个)
- 添加监听器(聚合报告、图形结果)
- 运行并分析结果
注意: JMeter 默认的 GUI 模式本身会消耗资源。大规模压测时,一定要用 jmeter -n -t test.jmx -l result.jtl 命令行模式运行。我曾经在 GUI 模式下压测 500 并发,结果 JMeter 自己先 OOM 了,尴尬。
1.4 知识体系总览
下面这张图,把本章的核心逻辑串起来了。从指标定义到目标设定,再到环境搭建,是一条完整的链路。
1.5 本章小结
嗯,到这里,第一章的核心内容就差不多了。总结一下:
- 指标:盯住 QPS、TP99、延迟、错误率,别被平均数据骗了
- SLA:结合业务场景和历史数据设定,留 1.5-2 倍余量
- 环境:内网部署、资源隔离、监控配套,缺一不可
- 工具:wrk 快速验证,JMeter 复杂场景,各取所长
记住一句话:没有基准的优化是盲目的,没有目标的压测是无效的。把这一章的基础打牢,后面的调优才有方向。