跳转到内容

性能问题

性能问题排查的第一步是确定瓶颈所在:CPU、内存、磁盘 I/O 还是网络。本文介绍常用的性能分析工具和排查方法。

在深入分析之前,先获取系统整体状态的快照。

一目了然:uptime 查看负载
$ uptime

输出示例:10:32:05 up 45 days, load average: 2.50, 1.80, 0.95

负载平均值(load average)分别是 1 分钟、5 分钟、15 分钟的平均值。作为参考,负载值不应长期超过 CPU 核心数。

查看 CPU 核心数
$ nproc
快速检查各项资源使用情况
$ free -h # 内存
$ df -h # 磁盘空间
$ uptime # 负载
$ sudo ss -s # 网络连接统计
启动 top
$ top

top 界面中的关键指标:

  • %us — 用户空间 CPU 使用率
  • %sy — 内核空间 CPU 使用率
  • %wa — 等待 I/O 的 CPU 时间(高值说明磁盘是瓶颈)
  • %id — 空闲 CPU 时间

常用操作:

  • 1 — 显示每个 CPU 核心的使用情况
  • P — 按 CPU 使用率排序
  • M — 按内存使用率排序
  • c — 显示完整命令行
非交互模式输出一次快照
$ top -bn1 | head -30

htop 提供更直观的界面,需要从 EPEL 安装:

安装 htop
$ sudo dnf install -y epel-release
$ sudo dnf install -y htop
启动 htop
$ htop

htop 中按 F6 选择排序方式,按 F5 切换树状视图。

安装 sysstat 工具包
$ sudo dnf install -y sysstat
每秒显示一次各核心 CPU 使用率,共 5 次
$ mpstat -P ALL 1 5
找出 CPU 使用率最高的前 10 个进程
$ ps aux --sort=-%cpu | head -11
查看指定进程的线程 CPU 使用情况
$ top -H -p <PID>
  • 应用程序 bug — 死循环、低效算法
  • 过多进程/线程 — 上下文切换开销大
  • 中断风暴 — 查看 /proc/interrupts
  • 编译或压缩任务 — CPU 密集型操作
查看上下文切换频率
$ vmstat 1 5

cs 列为上下文切换次数。每秒数万次以上可能影响性能。

查看内存使用情况
$ free -h

输出解读:

  • total — 物理内存总量
  • used — 已使用的内存
  • free — 完全空闲的内存
  • buff/cache — 被用作缓冲/缓存的内存(可回收)
  • available — 实际可用内存(free + 可回收的缓存)

重要: Linux 会积极使用空闲内存作为磁盘缓存,这是正常行为。判断内存是否不足应看 available 列,而不是 free 列。

每秒输出一次,共 10 次
$ vmstat 1 10

关键列:

  • si / so — 换入/换出页面数(swap)。持续大于 0 说明内存不足
  • free — 空闲内存(KB)
  • buff / cache — 缓冲和缓存内存
按内存使用率排序的进程列表
$ ps aux --sort=-%mem | head -11
查看指定进程的详细内存信息
$ cat /proc/<PID>/status | grep -E '(VmRSS|VmSize|VmSwap)'
查看 Swap 使用概况
$ swapon --show
查看哪些进程在使用 Swap
$ for pid in /proc/[0-9]*; do
name=$(cat $pid/comm 2>/dev/null)
swap=$(grep VmSwap $pid/status 2>/dev/null | awk '{print $2}')
[ -n "$swap" ] && [ "$swap" -gt 0 ] && echo "$swap kB - $name (PID: $(basename $pid))"
done | sort -rn | head -10
  • 内存泄漏 — 应用程序不断消耗更多内存
  • 缓存未释放 — 某些应用占用大量缓存
  • OOM Killer — 系统内存耗尽时自动杀死进程
查看 OOM Killer 历史记录
$ dmesg | grep -i "out of memory"
$ journalctl --since "7 days ago" | grep -i "oom-kill"
每秒输出一次磁盘 I/O 统计,共 5 次
$ iostat -x 1 5

关键指标:

  • %util — 磁盘利用率。持续接近 100% 说明磁盘已饱和
  • await — 平均 I/O 等待时间(毫秒)。HDD 正常在 5-20ms,SSD 在 0.5-2ms
  • r/s, w/s — 每秒读/写操作次数(IOPS)
  • rkB/s, wkB/s — 每秒读/写吞吐量
仅查看指定磁盘
$ iostat -x /dev/sda 1 5
安装 iotop
$ sudo dnf install -y iotop
查看实时 I/O 使用情况
$ sudo iotop -o

-o 参数仅显示有 I/O 活动的进程。

查看文件系统磁盘空间
$ df -h
查看 inode 使用情况
$ df -i

注意: 即使磁盘空间看起来未满,inode 耗尽同样会导致无法创建新文件。

找出占用空间最大的目录
$ sudo du -sh /var/log/* | sort -rh | head -10
找出大文件
$ sudo find / -xdev -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh | head -10
  • 日志文件过大/var/log 写满
  • 数据库 I/O 密集 — 查询未优化
  • Swap 频繁读写 — 实际是内存不足导致
  • RAID 降级 — 磁盘阵列性能下降
查看网络接口流量(每秒一次,共 5 次)
$ sar -n DEV 1 5

关键指标:

  • rxpck/s, txpck/s — 每秒收/发包数
  • rxkB/s, txkB/s — 每秒收/发字节数
  • %ifutil — 网络接口利用率
查看连接统计概览
$ ss -s
查看 TIME_WAIT 连接数
$ ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn

大量 TIME_WAIT 可能说明短连接过多。大量 CLOSE_WAIT 可能说明应用有 bug。

安装 iperf3
$ sudo dnf install -y iperf3
在服务端启动 iperf3
$ iperf3 -s
在客户端测试带宽
$ iperf3 -c <服务端IP>
  • 带宽饱和 — 流量超过网卡或链路容量
  • 丢包 — 网络质量差或缓冲区溢出
  • 连接数过多 — 超过系统或应用限制
  • DNS 延迟 — 每次请求都做 DNS 查询

sar(System Activity Reporter)可以回溯历史性能数据。

确保 sysstat 已安装并启用
$ sudo dnf install -y sysstat
$ sudo systemctl enable --now sysstat
查看今天的 CPU 使用历史
$ sar -u
查看今天的内存使用历史
$ sar -r
查看今天的磁盘 I/O 历史
$ sar -d
查看指定日期的数据(例如 20 号)
$ sar -u -f /var/log/sa/sa20
查看特定时间范围
$ sar -u -s 08:00:00 -e 12:00:00

按照以下顺序可以快速定位大多数性能问题:

负载与 CPU 核心数对比
$ echo "负载: $(cat /proc/loadavg | awk '{print $1, $2, $3}'), CPU 核心: $(nproc)"
使用 vmstat 初步判断
$ vmstat 1 5
  • us + sy 高 → CPU 瓶颈
  • wa 高 → 磁盘 I/O 瓶颈
  • si/so 持续大于 0 → 内存不足
  • 以上都正常但系统慢 → 可能是网络或应用层问题

根据第 2 步的结果,使用对应章节的工具进行深入分析。

使用 nice 降低进程优先级
$ nice -n 19 <命令>
使用 cpulimit 限制已运行进程的 CPU 使用率
$ sudo dnf install -y cpulimit
$ sudo cpulimit -p <PID> -l 50 # 限制到 50% CPU
创建 Swap 文件(应急)
$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
清理系统缓存(应急,不推荐常态化)
$ sudo sync && sudo sysctl vm.drop_caches=3
清理 dnf 缓存
$ sudo dnf clean all
清理旧的 journal 日志
$ sudo journalctl --vacuum-size=200M
删除旧内核(保留当前和一个备用)
$ sudo dnf remove --oldinstallonly --setopt installonly_limit=2 kernel

网络连接数过多:调整内核参数

Section titled “网络连接数过多:调整内核参数”
查看当前连接数限制
$ sysctl net.core.somaxconn
$ cat /proc/sys/net/ipv4/tcp_max_tw_buckets
临时增加连接限制
$ sudo sysctl -w net.core.somaxconn=65535
$ sudo sysctl -w net.ipv4.tcp_max_tw_buckets=65535