前阵子有个朋友去面字节,回来跟我吐槽,说面试官问了他一个问题:“假如某一天你的系统突然变慢了,变卡了,你会怎么办?”他说自己当时脑子里过了一遍top、free、df这些命令,但回答得没什么章法,面完出来才觉得这题其实考的不是命令背得熟不熟,而是面对一个模糊的“系统变慢了”的反馈,你到底有没有一套清晰的排查思路。
这个问题我太有感触了。做了这么多年后端和运维,系统变慢这种故障,基本是每个技术人都会遇到的噩梦。它难就难在“慢”这个字太笼统了——是用户觉得慢,还是监控发现慢?是新上的功能慢,还是全站都慢?是某个接口慢,还是数据库慢?如果你上来就一头扎进服务器敲命令,大概率会像无头苍蝇一样乱转,最后既浪费了时间,又挨了业务方的骂。
这篇文章我就结合自己的实际经验,把一套经过实战检验的排查思路完整地梳理一遍。不管你是刚入行的运维新人,还是写了几年业务代码的研发,这套方法论都适用。我会把从接到反馈、到定位问题、再到恢复和复盘的全过程拆开揉碎了讲,重点讲清楚每一步为什么要这么做,以及常见的坑在哪里。
先说一个总的指导思想:面对系统变慢,第一原则永远是——先恢复,再排查;先确认影响范围,再深入定位根因。千万不要一上来就纠结于“为什么”,而是要先用最快的方式把损失降到最低。后面所有的步骤,都是在这个原则下展开的。
1. 接到反馈后的第一步:别急着上服务器,先弄清楚“慢”到底指什么
很多人接到“系统变卡了”的消息,第一反应就是登录服务器,跑个top看看CPU是不是爆了。这个动作本身没错,但顺序错了。因为你连问题是什么都不知道,看top也看不出个所以然来。正确的做法是,先花两分钟把信息收集齐,搞清楚你面对的到底是一个什么样的问题。
1.1 先做“问题画像”:谁在说慢、哪里慢、从什么时候开始慢
我在实际处理故障时,通常会像一个医生问诊一样,先问自己几个固定问题:
- 反馈的人是谁?是外部用户打电话投诉,还是运营同学在后台发现数据刷不出来,还是测试环境联调时感觉卡?这直接决定了问题的优先级和影响范围。
- 所谓的“慢”是哪种慢?是打开网页要转圈半天,是个别操作点按钮没反应,还是接口返回数据要等几十秒?这决定了排查的方向。
- 是所有功能都慢,还是只有某个页面、某个接口慢?如果是局部的,那问题大概率出在那个功能对应的代码、数据库或者第三方依赖上;如果是全站的,那就要优先看基础设施和公共组件了。
- 是从什么时候开始变慢的?是刚刚才发生,还是从上一次发版之后就开始的?如果和发版时间点吻合,那大概率就是新代码引入的问题,回滚往往是最快的解决方案。
这几个问题问完,你基本就能把事情从一团乱麻中抽离出来了。这里我特别想强调一点:尽量去拿到“从什么时候开始”这个信息。我在排查故障时,最依赖的抓手就是时间线。只要能把“变慢”和某个时间点关联起来,你的排查范围就能缩小一大半,因为接下来的思路就是直接按时间点去反推那个时间节点前后系统发生了什么变更——是不是发版了、是不是有定时任务在跑、是不是数据库在做备份、是不是有运营同学在批量导数据。
1.2 确认影响面:这是“全站故障”还是“单点故障”
在你准备动手之前,还有一件必须要做的事:确认影响范围。这个步骤看起来很简单,但关键时刻能救命。
我的经验是,先看一眼监控大盘,或者随口问一句同事“你们那边卡不卡”。如果只是一个人反馈慢,可能只是他的网络问题、他的本地缓存问题,甚至是他自己电脑的问题;如果是整个业务线都在反馈慢,那就是全站级别的事故,需要立刻拉群、启动紧急响应流程了。
另外,还要区分是线上正式环境,还是测试环境。如果只是测试环境慢,那很多排查手段可以稍微放开一些,但在生产环境,你的每一步操作都要非常谨慎,因为线上系统经不起折腾。比如,线上环境jstack抓线程栈是相对安全的,但如果你贸然重启应用,那就可能把出现过问题的现场给破坏掉了,这个后面会详细说。
1.3 操作禁忌:千万不要一上来就重启
这一点我必须放在最前面讲,因为这是我见过太多人犯过的错误,包括我自己刚入行时也犯过。很多研发同学一遇到系统变慢,第一反应就是“重启一下试试”。如果是在确认是死锁、内存溢出、线程池耗尽这些问题时,重启确实是最快的止损手段,但如果原因还没定位,你一重启,所有的现场就全没了——线程栈没了、堆内存快照没了、网络连接状态没了、临时文件也没了。
所以,我的铁律是:重启是最后的兜底手段,而不是第一排查手段。除非系统已经濒临不可
