Java

值班现场第一眼该开 top、pidstat、ss 还是 iostat?我一般这样选

`top`、`pidstat`、`ss`、`netstat`、`iostat` 真正难的不是会不会敲,而是值班时第一眼先开哪一个。先把问题压到整机、进程、连接还是磁盘这一层,再决定要不要继续往 JVM 或数据库下钻,会比工具对照表更贴近现场。

  • Linux
  • 性能排查
  • top
  • pidstat
  • iostat
14 分钟阅读

系统命令这件事,平时最容易学成一个“我都知道一点”的状态。

你知道:

  • top 能看整机
  • pidstat 能看进程和线程
  • ss 看连接
  • netstat 也能看连接
  • iostat 看磁盘 I/O

可真到值班现场,难点往往不是这些定义,而是告警一来,你第一眼到底先开什么。

因为现场不是五选一的问答题,而是时间很紧、信息很乱:

  • 服务慢了,但你还不知道是 Java 自己忙,还是下游连接堆住了
  • CPU 没特别高,load 却不好看
  • 连接数像多了,但又不确定是不是主因
  • RT 抬高时,磁盘、网络、线程池、数据库都可能沾边

这时候如果按工具表并排去看,很容易每个都开一下,最后什么都看了,又什么都没先看清。

我现在更习惯把它当成一个值班第一眼的问题:

我先把异常压到哪一层?是整机、进程、连接,还是磁盘?

一旦这一层先压出来,后面要不要去 JVM、数据库、下游服务继续钻,才会顺。

所以这篇不做工具对照表,只讲我值班时更常见的几个起手判断。

一、如果我还不知道问题在哪层,第一眼几乎总是 top

大多数现场,top 还是最自然的第一屏。

不是因为它最强,而是因为它最快帮我回答几个值班时最朴素的问题:

  • 整机 CPU 是不是高
  • load 是不是离谱
  • 内存和 swap 有没有明显异常
  • iowait 有没有抬头
  • 哪个进程最值得盯
top

这一步的意义,不是定位根因,而是先定气氛。

比如我最常见的几种第一眼分流:

1. CPU 很高,某个 Java 进程顶在前面

那我后面大概率会往这个进程继续钻,通常是 pidstat,再往 JVM 工具走。

2. CPU 不算夸张,但 iowait 很高

这时候我就不会急着怀疑 Java 代码本身写坏了,反而会很快想到磁盘层,后面通常接 iostat

3. load 不低,但 CPU 也没高到解释一切

这类场景经常是线程等待、I/O 堵塞、连接问题或者 D 状态任务在作怪。也就是说,问题未必在“忙算”,而在“忙等”。

4. 整机其实还行,只有某个服务自己异常

那我就知道先盯进程,不用一开始就把锅往整台机器或底层资源上甩。

所以 top 在我这里更像总入口。它不给答案,但它能防止第一步就走错楼层。

二、top 已经告诉我“就是这个进程有问题”之后,我通常接 pidstat

一旦进程锁定了,pidstat 的价值就出来了。

pidstat -p <pid> 1

如果我怀疑是线程层面的问题,会直接看:

pidstat -t -p <pid> 1

为什么这一步很重要?因为 top 只告诉我“这个进程看起来不对劲”,但它不告诉我这个进程是怎么不对劲的。

而值班现场里,我常常马上就想知道:

  • 是几个线程特别忙,还是整体都忙
  • 是 CPU 真高,还是上下文切换很多
  • 是进程在打 I/O,还是只是在等

我怎么理解 pidstat 的位置

我会把它当成“进程内部的第二眼”。

  • top 像抬头看整栋楼
  • pidstat 像走进出事那一层看哪个房间在冒烟

如果 pidstat -t 已经看出某些线程异常忙,那后面通常就顺手接 jstack 或 Arthas thread

如果 pidstat -d 看出进程有明显读写压力,那我就会更谨慎,不会把问题简单归成 CPU 高或热点线程。

为什么这时我不先去看 ss

因为只要整机和进程层已经给出很明确的信号,我通常会先把这个方向走深一点。

除非现场一开始就是“超时很多、连接像炸了、端口看着不对”,否则我不会在进程刚锁定时立刻跳去看 socket 状态。那样容易在还没搞清主矛盾前,就把注意力切走。

三、如果现场第一感觉更像“连不上、超时多、连接怪”,我会优先开 ss

还有一类值班现场,描述本身就很像连接层问题:

  • 下游超时突然变多
  • 建连失败、重置连接、端口积压这类词开始出现
  • 某个服务请求卡住,但 CPU 并不解释得通
  • 大家开始怀疑是不是连接池、socket、端口状态出了问题

这种情况下,我不会死抱着 top -> pidstat 的顺序,而会更快去看 ss

ss -s
ss -ant
ss -lnt

我关心的其实不是命令本身,而是几件值班时很关键的事:

  • 连接总量是不是突然膨胀
  • 某种状态是不是堆得不正常,比如 SYN-SENTCLOSE-WAITTIME-WAIT
  • 某个目标 IP / 端口是不是特别集中
  • 监听端口和队列有没有异常

为什么我更常先想到 ss 而不是 netstat

很简单,ss 在现在的环境里通常更快,尤其连接多的时候更实用。

所以对我来说:

  • 现场连接态势要先看,现在先 ss
  • 老脚本、老机器、团队习惯里还在用 netstat,那它就作为补充

netstat 不是不能用,只是我很少把它当第一反应。

四、如果 top 里 iowait 一抬头,我通常马上补 iostat

不少现场最容易误判的一种情况是:

  • 服务慢
  • 大家下意识觉得是 Java 热点、数据库 SQL、线程池满了
  • 结果真正拖后腿的是磁盘层

所以我现在只要在 top 里看到 iowait 不好看,脑子里几乎会立刻接上 iostat

iostat -x 1

我主要想确认的是:

  • 是不是某个设备真的忙
  • await 是不是高得离谱
  • %util 有没有顶住
  • 队列是不是已经排起来了

这一步特别适合那种“CPU 没高到解释一切,但服务就是卡”的现场。

比如:

  • 日志盘被写慢了
  • 本地文件读写抖了
  • 宿主机底层存储不稳
  • 数据库所在盘本身有压力

为什么这时我不急着先回到 JVM 工具

因为如果底层 I/O 已经在拖整个服务,JVM 里看到的很多卡顿都可能只是结果。

先把磁盘这层确认掉,比急着去翻线程栈更能避免误判。

五、netstat 在我这里更像兼容工具,不太像第一眼工具

这不是说 netstat 没价值。

在老环境里、历史脚本里、某些团队协作场景里,它仍然很好用。

但如果问题是“值班第一眼先开谁”,我更常见的顺序还是:

  • 连接现场先 ss
  • 需要兼容传统脚本或补一些老视角时再用 netstat

也就是说,netstat 在我这里更像老朋友,不像冲在最前面的那个。

六、我值班时更常见的几条起手顺序

如果把上面这些压成更接近真实值班的几种场景,大概是这样。

1. 刚接现场,描述很模糊:服务慢了、机器卡了、还不知道哪层先坏

我通常会:

  1. top
  2. 如果进程明显异常,接 pidstat -p <pid> 1
  3. 如果 iowait 高,接 iostat -x 1
  4. 如果连接态势明显不对,再补 ss

2. CPU 高,已经看到 Java 进程冲上来

我通常会:

  1. top
  2. pidstat -t -p <pid> 1
  3. 再接 JVM 工具,比如 jstack 或 Arthas

这时候我不太会先看 ss,因为主矛盾已经更像进程 / 线程层。

3. 超时多、连接像出问题了,但 CPU 解释不通

我通常会:

  1. top 先扫一眼整机
  2. 很快转 ss -sss -ant
  3. 必要时再回头看应用线程、连接池、下游 RT

4. 服务卡、load 不好看、iowait 也抬头

我通常会:

  1. top
  2. iostat -x 1
  3. 再补 pidstat -d -p <pid> 1

因为这类现场最怕把 I/O 问题误判成代码热点。

七、我现在怎么记这几个命令

如果非要各记一句,我会这样记:

  • top:值班第一眼,先决定问题大概落在哪层
  • pidstat:进程锁定后,继续看它内部到底怎么忙
  • ss:怀疑连接状态和 socket 现场不对时,先看它
  • netstat:老环境和传统脚本的补充视角
  • iostat:一旦怀疑磁盘 I/O 在拖慢服务,先确认设备层

但更重要的其实不是这五句,而是一个顺序感:

先别急着把所有常见命令开一遍。先把异常压到整机、进程、连接或磁盘这一层,再决定往哪条线走。

只要这一步先收住,系统命令就不会再像一本工具手册,而更像值班时真正有用的第一组判断。