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. 收集历史数据:从监控系统拉取过去1-3个月的流量峰值、平均延迟
  2. 确定业务容忍度:和产品、运营聊,用户能等多久?超时多少会投诉?
  3. 设定初步目标:比如 TP99 500ms,QPS 2000
  4. 压测验证:跑一轮压测,看能不能达到
  5. 调整并固化:达不到就优化,或者调整目标(但别轻易降低标准)

小技巧: 设定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 都能处理。

基本步骤:

  1. 创建线程组(设置并发数、循环次数)
  2. 添加 HTTP 请求默认值(统一域名、端口)
  3. 添加 HTTP 请求(每个接口一个)
  4. 添加监听器(聚合报告、图形结果)
  5. 运行并分析结果

注意: JMeter 默认的 GUI 模式本身会消耗资源。大规模压测时,一定要用 jmeter -n -t test.jmx -l result.jtl 命令行模式运行。我曾经在 GUI 模式下压测 500 并发,结果 JMeter 自己先 OOM 了,尴尬。

1.4 知识体系总览

下面这张图,把本章的核心逻辑串起来了。从指标定义到目标设定,再到环境搭建,是一条完整的链路。

性能基准与目标设定 · 知识体系 核心性能指标 SLA 目标设定 压测环境搭建 工具选型 QPS/TPS TP99/TP999 延迟(Latency) 错误率 业务场景分析 历史数据收集 目标设定 压测验证 压测机配置 内网部署 资源隔离 监控配套 wrk(轻量) JMeter(全功能) 性能基准报告 + SLA 文档 💡 核心逻辑: 先定义指标 → 再设定目标 → 最后搭建环境验证。三者缺一不可,顺序不能乱。

1.5 本章小结

嗯,到这里,第一章的核心内容就差不多了。总结一下:

  • 指标:盯住 QPS、TP99、延迟、错误率,别被平均数据骗了
  • SLA:结合业务场景和历史数据设定,留 1.5-2 倍余量
  • 环境:内网部署、资源隔离、监控配套,缺一不可
  • 工具:wrk 快速验证,JMeter 复杂场景,各取所长

记住一句话:没有基准的优化是盲目的,没有目标的压测是无效的。把这一章的基础打牢,后面的调优才有方向。