性能优化度量指标:RT、QPS、TPS、并发数、吞吐率、CPU 利用率
你知道你的系统 QPS 是多少吗?
不是「大概」「估计」「应该」,而是精确的数字。
如果回答不上来,那这篇文章就是为你写的。
做性能优化,第一步是知道测量什么。如果连指标都说不清楚,那优化就是瞎子摸象。
六大核心指标
1. RT(Response Time):响应时间
响应时间是用户发起请求到收到响应的完整时间。
RT = T1 + T2 + T3 + ... + Tn其中 T1、T2 等是请求经过的每一个环节的耗时。
常见的 RT 指标:
| 指标 | 说明 | 用户感知 |
|---|---|---|
| P50 | 50% 的请求响应时间 | 中位数体验 |
| P90 | 90% 的请求响应时间 | 多数用户体验 |
| P99 | 99% 的请求响应时间 | 绝大多数用户体验 |
| P999 | 99.9% 的请求响应时间 | 极端情况体验 |
为什么需要这么多百分位?
想象一下:你的系统 P50 是 50ms,P90 是 100ms,P99 是 500ms。这意味着什么?
- 50% 的用户觉得很快(50ms)
- 40% 的用户觉得还行(50-100ms)
- 9% 的用户觉得慢(100-500ms)
- 1% 的用户可能会骂人(>500ms)
P99 才是服务的真实水平。 平均值会被极端值拉偏,P99 更能反映用户的真实体验。
2. QPS(Queries Per Second):每秒查询数
QPS 是指系统每秒能处理的请求数量。
QPS = 总请求数 / 总时间(秒)假设你的系统在 1 分钟内处理了 60,000 个请求,那么 QPS = 60,000 / 60 = 1000。
QPS 的重要性:
QPS = 100:小型内部系统
QPS = 1000:普通互联网应用
QPS = 10000:中型互联网应用
QPS = 100000+:大型互联网平台3. TPS(Transactions Per Second):每秒事务数
TPS 和 QPS 很相似,但有一个关键区别:TPS 是事务级别的,QPS 是请求级别的。
一个用户请求可能包含多个数据库查询:
用户下单(1个请求)
├── 查询商品(1个SQL)
├── 查询库存(1个SQL)
├── 查询用户信息(1个SQL)
├── 创建订单(1个SQL)
└── 扣减库存(1个SQL)这个请求的 QPS = 1,但 TPS(事务数)= 1,数据库 TPS = 5。
4. 并发数(Concurrency)
并发数是指系统同时处理的请求数量。
并发数 = QPS × 平均响应时间假设 QPS = 1000,平均响应时间 = 100ms,那么:
并发数 = 1000 × 0.1 = 100这意味着你的系统需要同时维护 100 个并发连接。
并发数和 QPS 的关系:
- QPS 高 ≠ 并发数高(比如每个请求只需要 1ms,QPS=1000,并发数只有 1)
- 并发数高 ≠ QPS 高(比如每个请求需要 10s,QPS=100,并发数是 1000)
5. 吞吐率(Throughput)
吞吐率是指单位时间内系统处理的数据量,通常用 MB/s 或 GB/s 表示。
吞吐率 = 数据量 / 时间这个指标常用于网络带宽、磁盘 I/O、数据库 I/O 等场景。
6. CPU 利用率(CPU Utilization)
CPU 利用率是指 CPU 实际处理任务的时间占总时间的比例。
CPU 利用率 = CPU 实际工作时间 / 总时间CPU 利用率的陷阱:
- CPU 利用率低 ≠ 系统不繁忙(可能是 I/O 阻塞)
- CPU 利用率高 ≠ 系统效率高(可能是死循环、锁竞争)
指标之间的关系
┌─────────────────────────────────────┐
│ 系统容量 │
│ │
│ QPS = 并发数 / 平均响应时间 │
│ │
│ RT = 并发数 / QPS │
│ │
└─────────────────────────────────────┘经典的性能公式:
并发数 = QPS × 平均响应时间举例:
| 场景 | QPS | RT | 并发数 | 说明 |
|---|---|---|---|---|
| 低并发 | 100 | 100ms | 10 | 每个请求快,但并发低 |
| 高并发 | 1000 | 100ms | 100 | 请求多,并发也高 |
| 长任务 | 10 | 10000ms | 100 | 每个请求慢,但并发可控 |
性能测试类型
基准测试(Benchmark Test)
在固定环境下,测试单一功能的性能。
public class BenchmarkTest {
public static void main(String[] args) {
// 预热:JIT 编译、CPU 频率稳定
for (int i = 0; i < 10000; i++) {
process();
}
// 正式测试
int count = 100000;
long start = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
process();
}
long duration = System.currentTimeMillis() - start;
System.out.printf("QPS: %.2f%n", (double) count / duration * 1000);
}
}负载测试(Load Test)
逐步增加压力,测试系统在不同负载下的表现。
压力曲线:
并发数 ─────────────────────────────────────
│
100│ ╭──────╮
│ ╭────╯ ╰───── 超出处理能力
│ ╭──╯ ✕ 系统崩溃
50│ ╭──╯
│ ╭───╯
│ ╭───╯
0└────┴───────────────────────────────────▶ 时间
0 1 2 3 4 5 分钟压力测试(Stress Test)
超过系统设计能力的高负载测试,寻找系统崩溃点。
容量规划(Capacity Planning)
根据业务增长预测,计算未来需要的系统容量。
public class CapacityCalculator {
/**
* 根据目标 QPS 和响应时间计算所需并发线程数
*/
public int calculateThreads(long targetQPS, long targetRTMillis) {
// 考虑 20% 的余量
double targetRT = targetRTMillis * 1.2 / 1000.0;
return (int) Math.ceil(targetQPS * targetRT);
}
/**
* 根据并发数和线程数计算预估 QPS
*/
public long estimateQPS(int concurrency, long avgRTMillis) {
// Little's Law: QPS = 并发数 / 平均响应时间
return (long) (concurrency * 1000.0 / avgRTMillis);
}
}监控方案
实时监控指标
# Prometheus 配置示例
metrics:
- name: http_request_duration_seconds
type: histogram
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5]
labels:
- method
- endpoint
- status
- name: jvm_memory_used_bytes
type: gauge
labels:
- area常用监控工具
| 工具 | 用途 | 特点 |
|---|---|---|
| Prometheus + Grafana | 指标采集+展示 | 生态丰富,查询强大 |
| Skywalking | APM 全链路追踪 | 支持分布式追踪 |
| Arthas | Java 应用诊断 | 在线诊断,无需重启 |
| Pinpoint | APM 全链路追踪 | 韩国团队出品,无代码侵入 |
总结
性能优化的第一步,是知道测量什么。
记住这张表:
| 指标 | 定义 | 公式 |
|---|---|---|
| RT | 响应时间 | 请求开始到结束 |
| QPS | 每秒请求数 | 总请求 / 总时间 |
| TPS | 每秒事务数 | 事务数 / 总时间 |
| 并发数 | 同时处理的请求 | QPS × RT |
| 吞吐率 | 单位时间处理量 | 数据量 / 时间 |
| CPU利用率 | CPU 工作占比 | CPU时间 / 总时间 |
思考题
你的系统 P99 响应时间是多少?如果超过 1 秒,用户体验会受到什么影响?
假设你的系统 QPS 从 1000 增长到 5000,但服务器只能增加 2 台——你能承受吗?怎么算?
CPU 利用率 80%,但响应时间很慢——这可能是什么原因?除了 CPU,还有哪些隐藏的瓶颈?
