USE 方法 · 资源的三个信号,精髓在饱和度
Utilization、Saturation、Errors —— Brendan Gregg 的资源监控方法论。这一章讲清三者的区别、为什么「饱和度」才是精髓(使用率 100% 不一定有问题,饱和度 > 0 一定有),并给出 CPU/内存/磁盘/连接池的具体 PromQL。
USE 方法 · 资源的三个信号,精髓在饱和度
RED 测服务,USE 测资源。它由性能大师 Brendan Gregg 提出,针对每一类资源问三个问题:
| 信号 | 全称 | 问题 |
|---|---|---|
| U | Utilization | 使用率:忙的时间占比(或已用容量占比) |
| S | Saturation | 饱和度:排队的程度——有多少工作在等 |
| E | Errors | 错误:这个资源报了多少错 |
精髓在 S。 这一章讲清为什么。
使用率 ≠ 有问题
最反直觉、也最重要的一条:使用率 100% 不一定有问题;饱和度 > 0 几乎一定有问题。
想象一个收银台:
- 使用率 100% —— 收银员一刻不停在扫码。这是好事! 说明资源被充分利用,没浪费。只要没人排队,顾客体验完美。
- 饱和度 > 0 —— 有人在排队。这一刻起,顾客开始等待——延迟产生了。
使用率衡量“资源在忙吗”,饱和度衡量“有人在等吗”。用户感知的是后者,不是前者。
这解释了一个常见的错误认知:很多团队看到“CPU 90%”就紧张,看到“CPU 40%”就放心。但真相是:
- CPU 90% 但 load 很低、没有排队 —— 系统跑得很好,资源利用充分。恭喜,你的钱花得值。
- CPU 40% 但线程都堵在锁上 —— CPU 闲着,但请求全在排队。用户体验已经崩了,而你的 CPU 面板一片绿。
只看使用率会同时导致误报和漏报。 这就是 USE 把饱和度单列为一个一等信号的原因——它是最接近用户痛苦的资源指标。
各类资源怎么测
USE 的用法是:列出你所有的资源,给每个都填这三格。
| 资源 | Utilization | Saturation ★ | Errors |
|---|---|---|---|
| CPU | 非空闲时间占比 | run queue 长度 / load | (罕见)机器校验错 |
| 内存 | 已用 / 总量 | swap 换页、OOM kill 次数 | OOM |
| 磁盘 IO | 设备忙时占比 | IO 队列深度、await | IO 错误 |
| 网络 | 带宽占比 | 丢包、重传、队列溢出 | 网卡错误 |
| 连接池 | 已用连接 / 上限 | 等待连接的线程数 / 等待时长 ★ | 获取连接超时 |
| 线程池 | 活跃线程 / 上限 | 队列里排队的任务数 ★ | 拒绝的任务数 |
表里打 ★ 的那两行(连接池、线程池)最值得注意——它们是应用层的资源**,而且是最常见的隐形瓶颈。**
很多“服务变慢”的事故,机器指标全是绿的(CPU 30%、内存 50%、磁盘闲),但数据库连接池满了,所有请求都在排队等连接。这时:
- Utilization = 100%(连接都被占着)
- Saturation = 一堆线程在等 ← 这才是用户感受到的那 2 秒
- 而 CPU/内存/磁盘 全部正常
如果你只对机器资源做 USE、不对应用层资源做,这类故障你会完全瞎掉。 连接池、线程池、队列、信号量、限流器——任何“有容量上限、会被占用、会让人排队”的东西都是资源,都该上 USE。
实战建议:连接池的“等待时长”是最有价值的单个指标之一。 它直接等于“用户为了拿到一个连接而多等的时间”。很多连接池库(HikariCP、Go 的 database/sql)都能吐这个,务必采它。
具体 PromQL(可以直接抄)
基于 node_exporter 的常用查询:
# ── CPU ──
# U:使用率(非 idle 时间占比)
1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))
# S:饱和度 —— load 除以核数(> 1 表示有排队)
node_load5 / count by (instance) (node_cpu_seconds_total{mode="idle"})
# ── 内存 ──
# U:使用率
1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
# S:饱和度 —— 换页速率(> 0 就该警觉)
rate(node_vmstat_pswpin[5m]) + rate(node_vmstat_pswpout[5m])
# ── 磁盘 IO ──
# U:设备忙时占比
rate(node_disk_io_time_seconds_total[5m])
# S:饱和度 —— 加权 IO 时间(反映队列深度)
rate(node_disk_io_time_weighted_seconds_total[5m])
# ── 网络 ──
# S:饱和度 —— 丢包
rate(node_network_transmit_drop_total[5m]) + rate(node_network_receive_drop_total[5m])
# E:错误
rate(node_network_transmit_errs_total[5m]) + rate(node_network_receive_errs_total[5m])注意 CPU 饱和度那条:node_load5 / 核数。 load 是个容易被误读的指标:
- Linux 的 load 包含 D 状态(不可中断睡眠,通常是等 IO)的进程,不只是等 CPU 的。所以 load 高不一定是 CPU 忙,可能是磁盘慢——这是个经典的误诊来源。
load / 核数 > 1只是粗略说明“排队了”。更准确的 CPU 饱和度应该看 PSI(Pressure Stall Information,/proc/pressure/cpu),它直接告诉你“因为等 CPU 而损失的时间占比”——这正是饱和度的精确定义。较新的node_exporter支持node_pressure_cpu_waiting_seconds_total,有的话优先用它。
# 更好的 CPU 饱和度:PSI(因等 CPU 而停顿的时间占比)
rate(node_pressure_cpu_waiting_seconds_total[5m])USE 的落地清单
Gregg 给的用法是一张表**,不是一堆面板:列出每个资源,逐格填。填不出来的格子,就是你的监控盲区。**
资源 U S E
─────────────────────────────────
CPU ✅ ✅ -
内存 ✅ ✅ ✅
磁盘 ✅ ✅ ✅
网络 ✅ ❓ ←盲区! ✅
DB 连接池 ✅ ❓ ←盲区! ✅
线程池 ❓ ❓ ←盲区! ❓这张表的价值在于它让“盲区”显式化。 大多数团队做完这张表会发现:机器资源填得挺满,应用层资源(连接池、线程池、队列)几乎全是问号——而那恰恰是最常出事的地方。
先把 ★ 那几个饱和度补上,收益立竿见影。
RED 和 USE 怎么配合
小结与下一章
USE = Utilization、Saturation、Errors,对每一类资源问这三个问题。精髓是饱和度:使用率 100% 不一定有问题(资源充分利用是好事),饱和度 > 0 几乎一定有问题(有人在排队 = 用户在等)——只看使用率会同时误报和漏报(CPU 90% 无排队 = 很健康;CPU 40% 全堵在锁上 = 已崩但面板全绿)。关键盲区是应用层资源(连接池 / 线程池 / 队列)——机器指标全绿而连接池排满是最常见的隐形事故,连接池等待时长是最有价值的单个指标之一。CPU 饱和度用 load/核数 只是粗略(load 含 D 状态进程,高不一定是 CPU 忙),有 PSI 优先用 PSI。USE 的用法是一张表,让盲区显式化。配合上:RED 是症状(服务出事了),USE 是病因(哪个资源的锅);都没饱和 → 瓶颈在下游,递归查下游的 RED。
第三套方法论来自 Google SRE,和 RED 高度重叠但视角不同。下一章讲清它们的关系。👉 四大黄金信号。