ps命令
下面给你两部分内容:
-
对你这份
ps -o pid,tid,stat,wchan:35,pcpu,comm -Lp 25964输出的分析 -
ps -o还能有哪些关键参数(完整清单/推荐组合)
一、你这个输出的分析(重点:性能瓶颈在哪里)
1)绝大多数线程在 futex_wait_queue_me
你输出里绝大部分线程状态是:
Ssl futex_wait_queue_me
含义是:
-
S:sleep(睡眠) -
s:可中断 sleep -
l:有本地锁(lock)
futex_wait_queue_me 是 Linux 内核的 futex 等待队列,通常表示:
-
Java 线程在等待锁(synchronized / ReentrantLock / condition)
-
或者在等待队列(BlockingQueue.take / Object.wait / CountDownLatch.await)
-
或者在等待线程池/队列/信号量
结论:
当前 Kafka 进程里大量线程处于“等待锁/等待队列”,并非 CPU 密集型。
2)有少量线程 CPU 高(17%+)
你输出里有一批线程 pcpu 17.6 ~ 18.2:
26422 17.6 futex_wait_queue_me
26423 17.6 futex_wait_queue_me
...
26426 18.2 futex_wait_queue_me
虽然也在 futex_wait_queue_me,但 CPU 占用却很高,这说明:
-
这些线程很可能在 忙等(busy spin) 或者
-
在不停的尝试获取锁(锁竞争非常激烈)
-
或者 JVM GC/内部线程在频繁轮询
结论:
你遇到的“性能问题”很可能不是“单线程 CPU 高”,而是 锁竞争/线程大量等待导致系统效率低。
3)ep_poll 线程:IO 等待
你有很多线程在 ep_poll:
26432 ep_poll 4.9
26433 ep_poll 4.5
...
ep_poll 表示:
-
网络 IO / socket 事件等待(Kafka 网络层 NIO)
-
这些线程处于等待状态,但 CPU 仍然有占用,可能是:
-
大量连接
-
大量请求
-
网络负载高
-
线程池大小过大导致上下文切换
-
4)Rsl 的线程:Running + sleeping lock
Rsl 表示:
-
R:running(运行中) -
s:可中断 sleep -
l:持有本地锁
这类线程可能是:
-
正在处理请求(但在某个锁上)
-
或者处于短暂运行状态
二、你的问题核心是什么?
从你这份输出可以推断:
结论:
Kafka 进程当前不是 CPU 饱和型,而是“线程等待/锁竞争/网络 IO”型。
你需要进一步确认:
-
哪些线程是 “真实业务线程”
-
哪些线程在
futex上等待的锁是谁持有 -
是否出现大量线程堆积(线程池配置过大)
三、如何进一步定位(你现在缺少关键点)
ps 只能告诉你线程在等待什么,但不能告诉你具体 Java 线程名、堆栈。
要进一步定位,你必须拿到 Java 线程栈。
你之前 jstack -F 报错,说明:
-
JVM 可能是 OpenJDK 8u201
-
或者进程处于某种状态(内存损坏、coredump、容器/权限、seccomp 等)
-
也可能是 系统与 JVM 版本不匹配(
jstack与 JVM 不一致)
你可以用 gcore 生成 core dump,再离线分析。
四、ps -o 关键参数(完整清单/推荐)
ps -o 的字段很多,我把你最常用、最有价值的列出来:
1)线程/进程识别相关
| 字段 | 含义 |
|---|---|
| pid | 进程 PID |
| tid | 线程 ID |
| ppid | 父进程 PID |
| pgid | 进程组 ID |
| sid | session ID |
| uid | 用户 ID |
| user | 用户名 |
| euser | 有效用户 |
| gid | 组 ID |
| comm | 命令名(可截断) |
| args | 全部命令行 |
| cmd | 同 args |
| command | 同 args |
2)状态/时间相关
| 字段 | 含义 |
|---|---|
| stat | 线程状态 |
| s | 进程状态(同 stat) |
| etime | 运行时间 |
| time | CPU 时间 |
| start_time | 启动时间 |
| lstart | 启动时间(完整格式) |
| cputime | 总 CPU 时间 |
| vsz | 虚拟内存 |
| rss | 物理内存 |
| pmem | 内存占比 |
| pcpu | CPU 占比 |
3)内存/CPU/IO 相关
| 字段 | 含义 |
|---|---|
| vsz | 虚拟内存大小 |
| rss | 常驻内存 |
| pmem | 内存占比 |
| pcpu | CPU 占比 |
| nice | nice 值 |
| pri | 优先级 |
| c | CPU 利用率 |
| %cpu | 同 pcpu |
4)等待/锁/调度相关(你现在最需要)
| 字段 | 含义 |
|---|---|
| wchan | 线程等待的内核函数 |
| wchan_name | 同 wchan |
| wchan_fmt | 同 wchan |
| cls | 调度类 |
| rtprio | 实时优先级 |
| policy | 调度策略 |
5)网络/IO/资源相关
| 字段 | 含义 |
|---|---|
| tty | 终端 |
| rss | 物理内存 |
| min_flt | 次缺页 |
| maj_flt | 主缺页 |
| maj_flt | 主缺页 |
| maj_flt | 主缺页 |
| blkio | blkio 统计(部分系统) |
五、推荐“最强 ps 输出组合”(你可以直接复制)
1)最强线程性能视图(CPU + wait + mem + args)
ps -eLo pid,tid,stat,pcpu,pmem,wchan:35,etime,time,comm,args --sort=-pcpu | awk '$1==25964' | head -200
2)线程等待函数聚合(找锁热点)
ps -eLo pid,tid,wchan --sort=wchan | awk '$1==25964 {print $3}' | sort | uniq -c | sort -nr | head -50
3)只看 CPU 高的线程
ps -eLo pid,tid,pcpu,stat,wchan:35,comm --sort=-pcpu | awk '$1==25964' | head -50
六、你下一步需要做什么?
你现在的 ps 输出只能说明:线程多、锁/IO 等待多、CPU 占用不是关键。
要真正定位问题,必须拿到:
1)Java 线程栈(jstack / jcmd / gcore)
你的 jstack 报错需要解决。
2)Kafka 自身指标(JMX / metrics)
比如:
-
request handler queue size
-
network processor queue size
-
consumer lag
-
GC pause time
如果你愿意,我可以继续帮你
请你补充两点,我就能给出精确的定位步骤:
-
你这台机器的 Kafka 版本 和 JVM 参数(特别是 -Xms -Xmx / GC / 线程池)
-
你要分析的是什么问题:
-
线程多导致系统慢?
-
CPU 高?
-
Kafka 消费/生产延迟?
-
GC 频繁?
-
还是 jstack 报错导致无法定位?
-
你回复后,我会给你一套“可执行的排查流程 + 命令 + 判断标准”。
1. 线程级别(更全面的 ps / top)
1.1 线程列表(带线程名、CPU、内核等待、内存、运行时间)
ps -eLo pid,tid,comm,stat,wchan:25,pcpu,pmem,etime --sort=-pcpu | awk '$1==14453' | head -200
-
comm:线程名(非常重要) -
wchan:内核等待函数 -
pcpu:线程 CPU 占用 -
pmem:线程占用内存(通常不敏感,但仍有用)
1.2 top 实时线程视图(最常用)
top -H -p 14453
按 P(CPU)或 M(内存)排序。
1.3 查看线程等待函数分布(统计)
ps -eLo pid,tid,wchan --sort=wchan | awk '$1==14453' | awk '{print $3}' | sort | uniq -c | sort -nr | head -50
可以看到 Kafka 线程集中在 futex_wait_queue_me / ep_poll 还是其他。
2. CPU 级别(系统/进程/线程)
2.1 pidstat:线程级 CPU 统计(实时)
pidstat -t -p 14453 1 5
输出解释:
-
%usr:用户态 CPU -
%sys:内核态 CPU -
%guest:虚拟机 -
CPU:CPU 核心编号
2.2 perf top(实时热点分析,最强)
perf top -p 14453
如果你想看线程热点:
perf top -p 14453 -g
3. IO 级别(磁盘/网络)
3.1 iostat:磁盘 IO 监控(最关键)
iostat -x 1 5
关注:
-
%util(是否接近 100) -
await(是否高) -
avgqu-sz(队列长度)
3.2 pidstat IO(进程级 IO 统计)
pidstat -d -p 14453 1 5
3.3 iotop(实时 IO 排名)
iotop -oPa | head -20
4. 网络级别(连接/吞吐/延迟)
4.1 查看 Kafka 端口连接状态
ss -ntlp | grep 9092
ss -s
4.2 查看连接数、状态分布
ss -nt state established '( sport = :9092 )' | wc -l
ss -nt state close-wait '( sport = :9092 )' | wc -l
4.3 查看 socket 队列是否积压
ss -s | grep -E 'tcp:|connections'
5. JVM 层(GC / 堆 / 线程)
5.1 立即输出 JVM 参数(如果 attach 失败可跳过)
jcmd 14453 VM.flags
jcmd 14453 VM.command_line
如果 attach 不行,可以从 Kafka 启动脚本查看。
5.2 GC 日志(如果已开启)
如果你开启了 GC log,可以实时 tail:
tail -200 /path/to/gc.log
建议生产环境开启:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/kafka/gc.log
6. 关键命令:生成堆栈(如果 attach 失败,用 kill -3)
kill -3 14453
然后查看 Kafka 日志输出。
如果 kill -3 没有输出,说明 JVM 处于“内核阻塞”状态。
7. 最强“系统级”诊断:dmesg / vmstat / sar
7.1 系统整体负载
vmstat 1 5
7.2 系统网络/IO 报错
dmesg | tail -100
7.3 资源利用历史(如果安装 sar)
sar -u 1 5
sar -d 1 5
8. 一条命令搞定“更全”的线程信息(推荐)
如果你想一次性列出线程名、CPU、等待函数、以及时间:
ps -eLo pid,tid,comm,stat,wchan:25,pcpu,pmem,etime --sort=-pcpu | awk '$1==14453' | head -200
你现在最需要的输出
为了快速定位问题,请你执行下面三条命令,并把输出贴出来(越多越好):
ps -eLo pid,tid,comm,stat,wchan:25,pcpu,pmem,etime --sort=-pcpu | awk '$1==14453' | head -200
pidstat -t -p 14453 1 5
iostat -x 1 5
wchan 是 ps 输出中用于显示 线程当前在内核中等待的函数(wait channel) 的字段。
而你问的 wchan:25 是一种 格式控制写法,用于控制输出宽度。
1. wchan 是什么?
在 Linux 中,每个进程/线程在进入内核等待时,会记录它正在等待的内核函数名,例如:
-
futex_wait_queue_me -
ep_poll -
read -
write -
fsync
wchan 就是显示这个等待函数名的字段。
2. wchan:25 的含义
在 ps 的 -o 格式中,字段:宽度 表示 输出字段宽度。
所以:
wchan:25
表示:
-
wchan字段的输出宽度 固定为 25 个字符 -
如果函数名不足 25 个字符,左对齐并填充空格
-
如果函数名超过 25 个字符,会被截断(通常不会超过太多)
3. 为什么要用 wchan:25?
因为 wchan 字段有时很长,例如:
futex_wait_queue_me
poll_schedule_timeout
ep_poll
为了让表格对齐更整齐,常用 :25 或 :20 来控制宽度。
4. 你可以改成其他宽度
例如:
-
wchan:20(更紧凑) -
wchan:35(更宽,不容易截断)
示例:
ps -o pid,tid,stat,wchan:35,pcpu,comm -Lp 14453
5. 你如果想要“自动适配宽度”,可以省略宽度
ps -o pid,tid,stat,wchan,pcpu,comm -Lp 14453
但输出可能会变得不整齐。
如果你希望我给你一个“最实用、最整齐、可读性最强”的 ps 命令格式,我可以直接给你一个标准模板。
浙公网安备 33010602011771号