系统突然变慢这个问题,我在面试里问过别人,也在实际生产环境里被问过无数次。大多数人的第一反应是“上去 top 看一眼”,这个没错,但如果只会 top,那你就永远停在“发现 CPU 高”这一步,没法真正回答“为什么慢”“卡在哪”。字节这场一面把问题设在“某一天突然变慢”,重点其实不是让你背命令,而是考察你在一个未知的、紧急的、影响面可能很大的故障面前,有没有一套稳定、可复现、能落地的排查思路。这篇文章,我就按自己实际处理故障的路径,把这个排查过程完整拆开讲讲。
1. 先建立排查框架,别急着找代码
很多人一上来就盯着某个进程、某个日志,这是典型的“先开枪后瞄准”。系统突然变慢,可能的原因太多了:流量突增、代码 bug、数据库抖动、网络延迟、磁盘写满、依赖服务超时、甚至是隔壁租户把宿主机资源吃光了。没有框架地乱撞,只会浪费时间,而故障处理最贵的就是时间。
1.1 为什么这个问题几乎是面试必考题
“系统变慢”是一个结果,不是一个原因。它背后是一个长长的因果链,从用户请求到应用处理,再到数据库返回,任何一个环节断裂都会被感知成“系统卡了”。面试官问这个问题,本质是想看你有没有建立一套完整的因果链认知。
我理解,一个合格的排查者脑子里应该有一张地图:请求链路经过哪些节点、每个节点有哪些风险点、哪些指标能反映这个节点的状态、哪些工具能拿到这些指标。没有地图的人靠猜,有地图的人靠定位。两者花费的时间可能是 10 分钟和一个下午的差距。
1.2 从现象到根因:一条主线,六个方向
我自己的排查逻辑可以归纳成一句话:从全局到局部,从系统到应用,从硬件到代码,逐层缩小包围圈。
展开来说,就是六个方向:
- 系统层:CPU、内存、磁盘、网络。这是最底层的资源,任何上层问题最终都会反映到资源的消耗或阻塞上。
- 应用层:进程状态、线程状态、GC、锁、日志。这是代码运行的地方,很多“慢”最终都表现为线程卡住、资源争抢。
- 中间件层:数据库、缓存、消息队列。分布式环境下,应用慢很多时候不是应用自己的问题,而是它依赖的东西慢了。
- 链路层:调用关系、依赖超时、重试机制。一个慢接口可能拖垮调用方,形成雪崩。
- 变更面:发布、配置、流量切换、数据迁移。大量故障都发生在变更之后,先查变更记录能省一半时间。
- 容量面:是否到达了系统瓶颈。比如线程池满了、连接池耗尽、带宽打满,这类问题不是“哪里坏了”,而是“不够用了”。
这六个方向不是每次都要全部排查,而是一个排查清单,按优先级和可能性逐个验证,快速排除。
1.3 排查前的三件事:确认“变慢”的定义、影响范围、变更记录
实战里,我第一次遇到线上告警时也是慌的,后来才总结出,动手之前必须先确认三件事,否则很容易被带偏。
第一,确认“变慢”的具体定义。是接口响应时间变长?还是页面加载变慢?还是定时任务跑不完?还是数据库查询卡顿?“慢”的表现不一样,排查路径完全不同。比如接口慢,可能是依赖超时;但定时任务慢,大概率是资源竞争或者数据量暴增。
第二,确认影响范围。是所有请求都慢?还是部分接口慢?是单台机器慢?还是整个集群慢?这个信息能快速区分是局部问题还是全局问题。如果只有一台机器慢,可以先怀疑这台机器的资源或者网络;如果整个集群都慢,那问题很可能出在下游公共依赖。
第三,必须要看变更记录。我相信每一个运维人都踩过这种坑:排查了半天,最后发现是前一天晚上发了一个新版本,或者改了一条配置。变更是故障的第一大诱因,排查前花两分钟确认有没有变更,能少走很多弯路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 第一轮体检:系统层四件套
框架搭好了,接下来就是动手。我的习惯是先用一套“系统层四件套”快速摸一遍全貌,也就是负载、CPU、内存、磁盘、网络这几个基础指标。这套操作熟练的话三五分钟就能完成,但是信息量非常大。
2.1 用 uptime 看负载,先判断是忙还是堵
登录服务器的第一件事,我一般是敲 uptime。它返回的是系统最近 1 分钟、5 分钟、15 分钟的平均负载(load average)。
code复制$ uptime
14:32:10 up 320 days, 2:41, 1 user, load average: 22.31, 18.07, 12.55
这个命令看起来简单,但读起来有门道。load average 是处于运行状态和不可中断状态的进程平均数量,它不是一个百分比,而是一个数值。看它要和 CPU 核数对比才有意义。比如一台 32 核的机器,负载 22 说明还有余量;但如果是 4 核的机器,负载 22 已经是灾难了。
三个时间点数值的变化趋势也很关键。如果 1 分钟负载远高于 15 分钟负载,说明系统是突然繁忙起来的,符合“突然变慢”的特征;如果三个数值都很高且接近,说明系统已经持续高负载很长时间了,可能是一个渐进式问题的爆发。
另外要注意,负载高不一定是 CPU 忙,也可能是 IO 等待。uptime 只能告诉你系统“忙不忙”,具体忙在哪,需要配合后面的命令看。
2.2 top:CPU 和内存的第一现场
第二站,top。这是绝大多数人熟悉的命令,但很多人只是看一眼 %CPU 最高的进程就完事了,这远远不够。
code复制$ top -c
top - 14:35:22 up 320 days, 2:44, 1 user, load average: 22.31, 18.07, 12.55
Tasks: 521 total, 1 running, 520 sleeping, 0 stopped, 0 zombie
%Cpu(s): 65.3 us, 8.2 sy, 0.0 ni, 22.5 id, 2.1 wa, 0.0 hi, 1.9 si, 0.0 st
MiB Mem : 128746.7 total, 102345.2 free, 8123.4 used, 18278.1 buff/c
