服务器与应用系统性能诊断及调优 - 第3节
一、为什么需要性能分析方法论?
刚开始做性能调优那会,我跟很多人一样。遇到系统慢,就怀疑代码写得烂。抓到哪个模块,就一顿瞎折腾。结果呢?有时候能蒙对,但大多数时候,CPU 分析了一通,发现瓶颈在磁盘。或者换个场景,根本找不到问题在哪。
说白了,没有方法论,性能调优就是无头苍蝇。你得有一套固定的打法,知道从哪下手,下一步该做什么。就像医生看病,得先有诊断流程,不能上来就开药。
我个人习惯,把性能分析方法论分成三个维度:
- 自上而下 —— 从用户视角往下看
- 自下而上 —— 从硬件资源往上看
- USE方法 —— 快速定位资源瓶颈
别急着记。我们一个个讲清楚,配合例子,你就知道什么时候该用哪个了。
二、先搞懂两个核心概念:延迟与吞吐量
在聊方法论之前,得先把这两个词整明白。不然你分析半天,都不知道自己在分析啥。
| 指标 | 定义 | 通俗理解 | 对应场景 |
|---|---|---|---|
| 延迟(Latency) | 单个请求从发出到完成的时间 | 点一下按钮,要等多久才出结果 | API 响应时间、数据库查询时间 |
| 吞吐量(Throughput) | 单位时间内系统能处理的请求数 | 一秒钟能服务多少人 | QPS、TPS、带宽利用率 |
你可能遇到过这种情况:给系统加了缓存,单个请求快了,但整体吞吐量却上不去。原因是缓存锁争用严重,CPU 大量时间花在等待锁上。所以啊,延迟和吞吐量不是简单的正相关。你得综合看。
嗯,这里要注意:调优之前先明确,你到底是要降延迟,还是提吞吐量。这两个方向的操作手法,有时候是冲突的。
三、自上而下法:从用户痛点出发
这是我最常用的方法。尤其是线上问题排查时。
思路是什么?
先把问题框定在“用户可感知”的层面。比如:
- 首页加载变慢了
- 下单接口超时了
- 文件导出要等半天
然后一层层往下剥离。从应用层 -> 服务层 -> 中间件层 -> 操作系统层 -> 硬件层。每一层都问一句:问题在这一层吗?
举个例子,我在项目中遇到过用户反馈“报表查询很慢”,大概要30秒。我开始排查:
- 第一层(应用层):检查代码逻辑,发现查询语句写得还算规范,没有明显的循环调用。
- 第二层(服务层):看日志,发现请求在排队等待数据库连接。
- 第三层(中间件层):检查连接池,最大连接数只有20,但并发请求有40个。找到问题了。
你看,我没一上来就去看 CPU 或者磁盘 I/O。因为用户感知到的问题是“慢”,但我不知道慢在哪。自上而下,就是帮我把搜索范围框定好,避免浪费精力。
适用场景
- 有明确的用户反馈或报警
- 问题可复现,且能定位到某个功能模块
- 整个链路你都有监控工具覆盖
缺点也明显
如果问题根本不在你业务链路上,比如某个基础软件升级导致性能下降,你自上而下查半天,可能都找不到根因。这时候就需要换个思路。
四、自下而上法:从硬件瓶颈开始啃
这种方法比较硬核。适合那些“系统没明显报错,但就是感觉不对劲”的场景。
我会从最底层开始:CPU、内存、磁盘、网络。一层层往上看。
操作流程
第一步:看 CPU —— 跑满了吗?上下文切换高不高?软中断多不多?
第二步:看内存 —— 剩余多少?是否在 swap 换页?
第三步:看磁盘 —— 平均服务时间、队列长度、IOPS 是否异常?
第四步:看网络 —— 带宽使用率、丢包率、连接数。
如果这些硬件层面都没问题,再往上面看:操作系统参数、中间件配置、应用程序逻辑。
一个真实的例子
我记得有次帮客户排查一个奇怪的问题:数据库偶尔会响应慢,但大部分时间正常。从上往下查,应用层没问题,SQL 执行计划也正常。我很头疼。
后来我改用自下而上法。先看磁盘,发现某块盘的队列深度经常飙到10以上,但盘本身是 SSD,理论上不该这么差。再往深挖,发现这块盘和另一台机器的日志盘共享了一个磁盘控制器。对方机器在跑全量备份,把带宽抢光了。
原因找到了。但如果我一直盯着应用层,永远看不到磁盘控制器层面的竞争。
什么时候用?
- 问题间歇性出现,难以通过用户操作复现
- 你怀疑是硬件或 OS 层面的问题
- 手上的监控工具覆盖了底层的指标(sar、iostat、vmstat 等)
五、USE方法:一个清单式的神器
这个方法我特别推荐。它简单,而且极其有效。尤其适合面试或者快速排查的时候用。
USE 是三个单词的缩写:
Utilization(使用率) —— 资源有多忙
Saturation(饱和度) —— 还有多少资源可用,或者请求在排队
Errors(错误) —— 有没有错误事件
对于每一个资源,你只需要问三个问题:
- 它的使用率高吗?(比如 CPU 90%)
- 它饱和了吗?(比如磁盘队列深度 > 2)
- 它在报错吗?(比如网络丢包率 > 0)
你看,就这么简单。任何一个资源,只要你发现其中一项异常,大概率就是它了。
一个实际的应用表格
| 资源 | 使用率指标 | 饱和度指标 | 错误指标 |
|---|---|---|---|
| CPU | 利用率(%usr + %sys) | 负载均值(load average),run queue 长度 | — |
| 内存 | 已用百分比 | Swap 使用量、OOM 事件 | OOM Killer |
| 磁盘 | 平均服务时间、IOPS / 理论上限 | 磁盘等待队列长度 | I/O 错误计数 |
| 网络 | 带宽利用率 | 连接队列溢出、丢包率 | 重传率、CRC 错误 |
你在排查时,照着这张表一项项查就行。我建议打印出来贴在工位上。真的,非常有用。
USE方法的精髓
它不关心你的业务逻辑。它只关心资源本身的状态。所以对于“我的系统跟屎一样慢,但就是不知道哪出了问题”这种问题,用它最合适。
我举个完整的例子:
# 检查 CPU
$ top -bn1 | head -5
# 看 load average 是否超过 CPU 核数
# 检查磁盘
$ iostat -x 1 3
# 看 %util 和 avgqu-sz
# 检查网络
$ netstat -s | grep -E "retransmit|overflow|drop"
嗯,就是这样的命令行。跑一遍,基本能锁定问题方向。
六、三种方法的对比与选择
你可能会问:那我到底该用哪个?
我的经验是:先用 USE 方法做快速扫描,再用自上而下或自下而上做深度定位。USE 方法像是一个体检的初筛,查出哪个器官有问题。然后针对性去做 CT(自上而下或自下而上)。
- 如果问题是 用户明确反馈的,你就从自上而下入手,快速定位到具体代码或配置
- 如果问题是 隐性的、间歇性的,优先用自下而上,从硬件层面找异常
- 如果你 完全没头绪,或者线上告警五分钟后才到,先从 USE 方法查一轮,把最明显的资源瓶颈排除掉
七、总结一下这三种打法
自上而下,就像从楼顶往下走,每层都看看有没有漏水的。适合有明确投诉的场景。
自下而上,是从地下室往上走,检查地基稳不稳。适合那种让人摸不着头脑的“系统抽风”。
USE方法,是个清单检查法。我建议你把它当成每台服务器上的“救命手册”。
你想想看,这套组合拳如果打熟了,遇到性能问题你还会慌吗?