欢迎光临
我们一直在努力

Linux 性能排查实战

在日常运维中,"机器很卡"是最常见也最模糊的问题描述。卡顿可能来自 CPU、内存、磁盘 IO、网络中的任何一个环节,也可能是特定场景下的局部问题。本文从系统整体卡顿、打字延迟、内存泄漏三个层面,给出一套可执行的排查方法论。

目录

一、系统卡顿排查框架

1.1 一键快速定位

1.2 分维度排查命令

1.3 判断逻辑

1.4 最常用的三板斧

二、打字卡顿专项排查

2.1 SSH 远程打字卡

网络延迟或丢包

SSH 服务端 DNS 反向解析

MTU 不匹配

2.2 本地终端打字卡

终端模拟器资源消耗高

桌面合成器卡顿

输入法进程卡死

Shell 配置过重

终端大量输出滚动

2.3 编辑器中打字卡

2.4 快速定位法

三、内存泄漏诊断

3.1 什么是内存泄漏

3.2 为什么要关注内存泄漏

3.3 常见内存泄漏场景

手动内存管理语言(C/C++)

缓存或集合只进不出

资源句柄未关闭

监听器和回调未注销

长生命周期对象持有短生命周期引用

第三方库缺陷

运维侧的类泄漏

3.4 排查方法

四、总结


一、系统卡顿排查框架

系统卡顿的本质是资源瓶颈。Linux 系统的核心资源有四类:CPU、内存、磁盘 IO、网络,加上一个综合指标负载(load average)。排查时先定位是哪个维度的问题,再深入分析。

1.1 一键快速定位

在排查初期,用一条命令获取全局概览:

uptime && echo "—" && top -bn1 | head -20 && echo "—" && free -h && echo "—" && vmstat 1 3

这条命令依次输出:系统负载、CPU 和进程概览、内存使用、虚拟内存统计。基本能在 10 秒内判断出卡顿方向。

1.2 分维度排查命令

维度

命令

关注指标

整体负载

uptime

load average 与 CPU 核数对比,超过核数即为过载

CPU 占用

top(按 P 排序)

%us 用户态、%sy 内核态、%wa IO 等待

CPU 核明细

mpstat -P ALL 1

是否单核打满、是否有软中断%soft

进程 CPU

pidstat -u 1

哪个进程持续消耗 CPU

内存

free -h

available 是否耗尽、swap 是否在用

内存进程

top(按 M 排序)

哪个进程占内存最多

换页

vmstat 1

si/so 持续非零说明在频繁 swap

磁盘 IO

iostat -xz 1

%util 接近 100%、await 高说明磁盘瓶颈

IO 进程

iotop 或 pidstat -d 1

哪个进程在大量读写

网络流量

iftop 或 nethogs

是否被打满带宽、哪个进程占流量

网络错误

sar -n DEV 1

rxerr/rxdrop 是否持续增长

异常进程

ps aux \\

awk '$8 ~ /D\\

系统日志

dmesg -T \\

tail -50

1.3 判断逻辑

根据 top 输出中的 CPU 状态,可以快速定位瓶颈类型:

• load 高 + %us 高:计算密集型进程,用 top 找 CPU 占用最高的进程

• load 高 + %wa 高:磁盘 IO 瓶颈,用 iostat 和 iotop 定位

• load 高 + %sy/%soft 高:内核或网络软中断开销大,检查网络包量和内核参数

• available 内存低 + swap 活跃:内存不足,检查是否有内存泄漏或进程占用过高

• %util 100% + await 高:磁盘性能不足或有坏道,检查 dmesg 中的 IO 错误

1.4 最常用的三板斧

如果时间有限,先执行这三条:

# 1. 谁在吃 CPU

top -bn1 | head -15

 

# 2. 谁在吃内存

ps aux –sort=-%mem | head -10

 

# 3. 是不是 IO 瓶颈

iostat -xz 1 3

二、打字卡顿专项排查

"打字卡"是一个比"系统卡"更具体的问题,通常不是全局资源问题,而是特定链路的延迟。需要区分场景来排查。

2.1 SSH 远程打字卡

这是最常见的场景,表现为按键后字符延迟出现,或者一串字突然一起蹦出来。

常见原因和解决方法:

网络延迟或丢包

用 ping 测试到服务器的网络质量,如果延迟高或有丢包,问题在网络层。弱网环境下可以用 mosh 替代 SSH,mosh 基于 UDP 且支持本地回显,体验远好于 SSH。

ping -c 20 <服务器IP>

SSH 服务端 DNS 反向解析

SSH 默认会对连接 IP 做反向 DNS 解析,如果 DNS 配置有问题,每次操作都会卡顿。禁用即可:

sudo sed -i 's/^#*UseDNS.*/UseDNS no/' /etc/ssh/sshd_config

sudo sed -i 's/^#*GSSAPIAuthentication.*/GSSAPIAuthentication no/' /etc/ssh/sshd_config

sudo systemctl restart sshd

MTU 不匹配

如果大包卡顿但小包正常,可能是 MTU 问题。用以下命令测试:

ping -M do -s 1472 <网关IP>

不通则说明 MTU 需要调小,或者在网关上配置 TCP MSS clamping。

2.2 本地终端打字卡

如果是在物理机或虚拟机的桌面环境中打字卡,原因通常在终端模拟器或桌面环境层面。

终端模拟器资源消耗高

gnome-terminal、konsole 等终端在某些情况下会占用大量 CPU。可以换用 alacritty 或 kitty,它们基于 GPU 加速,响应极快。

桌面合成器卡顿

KDE 的 KWin 合成器、GNOME 的动画效果可能导致输入延迟。尝试关闭合成器或禁用桌面动画。

输入法进程卡死

ibus 或 fcitx 输入法进程异常会导致输入卡顿。重启输入法:

ibus restart

# 或

fcitx5 -r

Shell 配置过重

如果每次回车都卡一下,可能是 shell 配置文件中有慢命令,比如 git 状态查询、复杂的 prompt 渲染。用裸 shell 对比测试:

bash –norc –noprofile

如果裸 shell 流畅,就需要精简 .bashrc 或 .zshrc,移除耗时插件,或者使用异步 prompt 方案如 powerlevel10k。

终端大量输出滚动

如果有进程在疯狂打印日志,终端渲染会成为瓶颈。用 Ctrl+S 暂停输出,Ctrl+Q 恢复,或者将输出重定向到文件。

2.3 编辑器中打字卡

只有在 vim 等编辑器中卡顿,通常是编辑器本身的问题:

• 插件过多或语法高亮在大文件下性能差:用 vim –noplugin 启动对比

• 文件过大:用 less 查看而非编辑,或用 vim -u NONE 裸启动

• 代码折叠导致卡顿:执行 :set nofoldenable 关闭折叠

• 交换文件写入慢:检查磁盘 IO 是否正常

2.4 快速定位法

按以下顺序测试,30 秒内可以定位问题层级:

# 1. 系统是否整体卡

uptime && top -bn1 | head -5

 

# 2. 排除 shell 配置问题

bash –norc –noprofile

 

# 3. 物理机切到 tty 测试(Ctrl+Alt+F3),排除图形环境影响

 

# 4. SSH 场景测试网络

ping -c 10 <服务器IP>

判断逻辑:

• tty 里也卡:系统负载或硬件问题

• tty 流畅但图形终端卡:终端模拟器、合成器或输入法问题

• 本地流畅但 SSH 卡:网络或 SSH 配置问题

• 只有某个编辑器卡:编辑器配置或大文件问题

三、内存泄漏诊断

内存泄漏是导致系统逐渐变慢、最终崩溃的常见原因。它的特点是渐进式的,容易被忽视。

3.1 什么是内存泄漏

内存泄漏的本质是:程序申请了内存但用完没有释放,导致可用内存随时间持续减少。

需要区分"内存占用高"和"内存泄漏":一个正常程序内存占用高但稳定是没问题的;一个泄漏程序哪怕每次只漏 1MB,长时间运行后也会耗尽所有内存。

3.2 为什么要关注内存泄漏

内存泄漏的危害是渐进的:

1. 初期几乎无感,内存占用缓慢上升

2. 中期可用内存不足,开始频繁使用 swap,系统明显变卡

3. 后期 OOM Killer 随机杀掉进程,服务崩溃

4. 极端情况下系统卡死,只能重启

因此在排查系统卡顿和服务不稳定时,内存使用趋势是必查项。

3.3 常见内存泄漏场景

手动内存管理语言(C/C++)

malloc/new 之后没有对应的 free/delete,或者函数提前返回、抛出异常时跳过了释放逻辑。

void bad_example() {

    char *p = malloc(1024);

    if (error) return;   // 直接返回,p 没有释放

    free(p);

}

缓存或集合只进不出

这是所有语言中最常见的泄漏类型。HashMap、List、全局缓存无限追加数据,但没有淘汰策略或清理机制。日志队列、任务队列的消费者跟不上生产者速度也属于此类。

// 典型泄漏:每个请求都 put,但从不 remove

static Map<String, Object> cache = new HashMap<>();

cache.put(requestId, data);

资源句柄未关闭

文件描述符、数据库连接、Redis 连接、Socket 没有正确关闭,这类泄漏最终会表现为 Too many open files 错误。线程创建后未退出也属于此类。

监听器和回调未注销

注册了事件监听器但对象销毁时没有反注册,定时器没有 cancel。常见于 GUI 程序、Android 开发、前端组件销毁场景。

长生命周期对象持有短生命周期引用

Java 中静态集合持有 Activity 或 Request 对象,导致整个对象图无法被 GC 回收。Python 中循环引用且定义了 __del__ 方法,引用计数无法回收。闭包捕获了大对象且闭包被长期持有也会导致泄漏。

第三方库缺陷

驱动、JNI 库、native 扩展可能存在内存泄漏。某些版本的框架(如 Netty、Tomcat 的特定版本)也有已知的内存泄漏问题。

运维侧的类泄漏

日志文件只写不轮转导致磁盘占满、Docker 容器的 json-file 日志无限增长、/tmp 临时文件不清理。这些不是严格意义上的内存泄漏,但现象和危害类似。

3.4 排查方法

判断是否存在内存泄漏,核心是观察内存使用趋势:

# 观察特定进程的内存趋势(每 2 秒采样)

pidstat -r -p <PID> 2

 

# 或者用 watch 监控 RSS

watch -n 5 'ps -o pid,rss,vsz,comm -p <PID>'

 

# 系统整体内存趋势

free -h

sar -r 1 10

判断标准:在没有新任务涌入的情况下,进程的 RSS(实际物理内存)持续单调上升且不回落,基本可以确定存在内存泄漏。正常程序在 GC 或空闲后内存会趋于平稳或下降。

不同语言有更专业的排查工具:

• Java:jmap 导出堆转储,用 MAT 或 JVisualVM 分析

• Go:pprof 分析内存分配

• C/C++:valgrind、AddressSanitizer

• Python:tracemalloc、objgraph

四、总结

Linux 性能排查的核心思路是:先全局后局部,先资源后进程。系统卡顿用五维度模型快速定位,打字卡顿按场景分层排查,内存泄漏看趋势而非绝对值。

掌握这套方法论后,面对"机器很卡"这类模糊问题时,就可以有条理地逐步缩小范围,最终找到根因。排查工具只是手段,理解各资源之间的关联和系统的运行机制才是关键。

赞(0)
未经允许不得转载:171主机测评 » Linux 性能排查实战
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址