文章

Linux 系统性能瓶颈分析: CPU, 内存, 磁盘, 网络四维排查法

在 [程序员面试吧] 公众号中找到的 Linux 系统性能分析

Linux 系统性能瓶颈分析: CPU, 内存, 磁盘, 网络四维排查法

原文: 程序员面试吧 - Linux 系统性能瓶颈分析: CPU, 内存, 磁盘, 网络四维排查法

1. 适用场景 & 前置条件

项目 要求
适用场景 服务器响应慢、应用卡顿、负载高、OOM 频繁、数据库慢查询、网络丢包
OS RHEL/CentOS 7.9+ 或 Ubuntu 20.04+
内核 Linux Kernel 3.10+(推荐 5.10+ 支持更多性能监控特性)
工具版本 sysstat 11.0+、perf 4.0+、iotop 0.6+、nethogs 0.8+
资源规格 无特殊要求(监控工具适用于任何配置)
权限 root 或 sudo 权限(某些工具需要)
技能要求 熟悉 Linux 进程管理、文件系统、网络协议栈、内核参数调优

2. 反模式警告 (何时不适用)

  1. 应用层逻辑问题:代码死循环、内存泄漏、算法复杂度高(应结合代码 profiling 工具如 pprof/py-spy)
  2. 分布式系统瓶颈:微服务调用链慢、消息队列积压(需使用 APM 工具如 SkyWalking/Jaeger)
  3. 数据库内部问题:索引缺失、查询计划不优(需数据库专用工具如 pt-query-digest/pgBadger)
  4. 硬件故障:磁盘坏道、内存条损坏、网卡故障(需硬件诊断工具)
  5. 云服务限流:云主机突发性能实例耗尽积分、云数据库 IOPS 限额(查看云厂商监控)

替代方案对比:

场景 推荐方案 理由
应用代码性能 Go pprof / Python py-spy / Java JProfiler CPU/内存火焰图、函数级耗时
分布式链路追踪 Jaeger / Zipkin / SkyWalking 跨服务调用链可视化
数据库性能 pt-query-digest / EXPLAIN ANALYZE SQL 级别优化建议
容器性能 cAdvisor / Prometheus 容器资源隔离监控
内核调试 SystemTap / eBPF (bpftrace) 内核函数级追踪、零侵入

3. 环境与版本矩阵

组件 RHEL/CentOS Ubuntu/Debian 测试状态
OS 版本 RHEL 8.7+ / CentOS Stream 9 Ubuntu 22.04 LTS [已实测]
内核版本 4.18.0-425+ (5.14+ 推荐) 5.15.0-60+ [已实测]
sysstat (sar/iostat) 12.5.4 12.6.0 [已实测]
perf 5.14 5.15 [已实测]
iotop 0.6 0.6 [已实测]
nethogs 0.8.7 0.8.7 [已实测]
dstat 0.7.4(已停止维护) 0.7.4 [已实测]

版本差异说明:

  • Linux 5.10+ 支持更多 eBPF 特性(bpftrace 工具依赖)
  • sysstat 12.0+ 支持 JSON 格式输出(便于 Prometheus 采集)
  • perf 5.0+ 支持火焰图生成优化

4. 阅读导航

📖 建议阅读路径:

快速上手(15分钟):→ 章节5(快速清单)→ 章节6(实施步骤 Step 1-4)→ 章节12(一键诊断脚本)

深入理解(60分钟):→ 章节7(最小必要原理)→ 章节6(实施步骤完整版)→ 章节11(最佳实践)→ 章节13(扩展阅读)

故障排查:→ 章节9(常见瓶颈对照表)→ 章节6.5-6.8(具体调优步骤)

5. 快速清单 (Checklist)

  • 工具准备
    • 安装 sysstat 工具集(yum install sysstat / apt install sysstat
    • 安装 perf 工具(yum install perf / apt install linux-tools-$(uname -r)
    • 安装 iotop / nethogs(yum install iotop nethogs
    • 启用 sar 数据采集(systemctl enable --now sysstat
  • CPU 维度排查
    • 查看整体 CPU 使用率(top / htop
    • 查看进程级 CPU 占用(ps aux --sort=-%cpu | head -20
    • 分析 CPU 上下文切换(vmstat 1 / pidstat -w 1
    • 查看 CPU 中断(cat /proc/interruptsmpstat -P ALL 1
    • CPU 火焰图分析(perf record + FlameGraph)
  • 内存维度排查
    • 查看内存整体使用(free -h / vmstat 1
    • 查看进程内存占用(ps aux --sort=-%mem | head -20
    • 分析内存泄漏(valgrind --leak-check=full
    • 查看 SWAP 使用(swapon -s / vmstat 1
    • OOM Killer 日志(dmesg | grep -i oom
  • 磁盘 IO 维度排查
    • 查看磁盘 IO 统计(iostat -x 1
    • 查看进程 IO 占用(iotop -o
    • 分析磁盘慢查询(iotop -P -a 累积模式)
    • 检查文件系统缓存(cat /proc/meminfo | grep -i cache
    • 磁盘健康检查(smartctl -a /dev/sda
  • 网络维度排查
    • 查看网络连接状态(ss -s / netstat -s
    • 查看进程网络占用(nethogs
    • 分析丢包与重传(netstat -s | grep -i retrans
    • TCP 连接队列(ss -lnt 查看 Send-Q / Recv-Q)
    • 网络延迟测试(ping / mtr

6. 实施步骤 (核心)

性能瓶颈分析四维模型

思路:

性能问题出现
    ↓
第一步:定位瓶颈维度(CPU/内存/磁盘/网络)
    ├─ 使用 top/htop 快速概览系统状态
    ├─ 查看 Load Average(1分钟/5分钟/15分钟负载)
    └─ 使用 dstat 同时监控四维指标
    ↓
第二步:针对性深入分析
    ├─ CPU 瓶颈 → 查看进程、线程、上下文切换、中断
    ├─ 内存瓶颈 → 查看 RSS/VSZ、缓存、SWAP、OOM
    ├─ 磁盘瓶颈 → 查看 IOPS、吞吐量、IO 等待、文件系统
    └─ 网络瓶颈 → 查看带宽、连接数、丢包率、延迟
    ↓
第三步:优化与验证
    └─ 应用调优措施 → 持续监控 → 对比优化前后指标

关键指标阈值:

维度 正常范围 警告阈值 严重阈值
CPU 使用率 < 70% 70-85% > 85%
Load Average (单核) < 1.0 1.0-2.0 > 2.0
内存使用率 < 80% 80-90% > 90%
SWAP 使用 0 MB > 0 但 < 10% 物理内存 > 10% 物理内存
磁盘 IO 等待 (%iowait) < 10% 10-30% > 30%
磁盘 IOPS (HDD) < 100 100-150 > 150
磁盘 IOPS (SSD) < 5000 5000-8000 > 8000
网络丢包率 0% 0-0.1% > 0.1%
TCP 重传率 < 1% 1-5% > 5%

6.1. CPU 维度排查

1. 查看整体 CPU 使用率

# 实时监控 CPU 使用(刷新间隔 1 秒)
top -d 1

# 关键指标解读:
# %Cpu(s): 14.3 us,  2.7 sy,  0.0 ni, 82.0 id,  0.7 wa,  0.0 hi,  0.3 si,  0.0 st
# us (user): 用户态 CPU 占用(应用程序)
# sy (system): 内核态 CPU 占用(系统调用、中断)
# ni (nice): 低优先级进程 CPU 占用
# id (idle): 空闲 CPU(理想 > 30%)
# wa (iowait): IO 等待 CPU(> 10% 表示磁盘瓶颈)
# hi (hardware interrupt): 硬件中断 CPU(> 5% 异常)
# si (software interrupt): 软件中断 CPU(网络处理)
# st (steal): 虚拟机被宿主机窃取的 CPU(云主机关注,> 10% 表示资源竞争)

# 使用 htop(更直观的交互式工具)
htop

# 按键说明:
# F2: 设置显示选项
# F3: 搜索进程
# F4: 过滤进程
# F5: 树状显示
# F6: 排序(CPU/MEM/TIME)
# F9: 杀死进程
# F10: 退出

判断 CPU 瓶颈

# 查看 Load Average
uptime
# 输出示例:
#  10:30:01 up 15 days,  3:45,  2 users,  load average: 4.50, 3.80, 2.10
# 解读:
# - 1 分钟负载:4.50(短期突发)
# - 5 分钟负载:3.80(中期趋势)
# - 15分钟负载:2.10(长期趋势)
# 判断标准:Load Average / CPU 核心数 > 1.0 表示 CPU 不足

# 查看 CPU 核心数
grep -c ^processor /proc/cpuinfo
# 输出:4(4 核心)
# 结论:4.50 / 4 = 1.125 > 1.0(CPU 接近饱和)

2. 查看进程级 CPU 占用

# 按 CPU 使用率排序查看前 20 个进程
ps aux --sort=-%cpu | head -20

# 输出示例:
# USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
# mysql     1234 85.3  5.2 2456784 524288 ?      Ssl  Jan10 1250:30 /usr/sbin/mysqld
# java      5678 45.2 12.3 4567890 1234567 ?     Sl   Jan09  850:15 java -jar app.jar
# nginx     9012  8.5  0.3  125000  32000 ?      S    Jan08   45:20 nginx: worker

# 持续监控单个进程 CPU(每秒刷新)
pidstat -p 1234 1

# 输出示例:
# 10:30:01      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
# 10:30:02      27       1234   75.00   10.00    0.00    0.00   85.00     2  mysqld
# 10:30:03      27       1234   78.00    9.00    0.00    0.00   87.00     2  mysqld

# 查看多线程程序的线程 CPU 使用
top -H -p 1234
# -H: 显示线程
# -p: 指定进程 PID

3. 分析 CPU 上下文切换

原理: 上下文切换过多会导致 CPU 浪费在进程切换而非实际计算

# 查看系统级上下文切换速率
vmstat 1

# 输出示例:
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
#  4  0      0 512000 102400 1024000    0    0     0    10 8500 25000 60 15 25  0  0
#  3  1      0 510000 102400 1024000    0    0     0    50 8600 28000 65 18 17  0  0

# 关键列:
# r: 运行队列长度(等待 CPU 的进程数,> CPU 核心数表示 CPU 不足)
# b: 不可中断睡眠进程数(通常是 IO 等待,> 0 表示磁盘瓶颈)
# in: 每秒中断次数(interrupts)
# cs: 每秒上下文切换次数(context switches)
# 正常值:cs < 10000,> 100000 表示异常

# 查看进程级上下文切换
pidstat -w -p 1234 1

# 输出示例:
# 10:30:01      UID       PID   cswch/s nvcswch/s  Command
# 10:30:02       27      1234    150.00   8500.00  mysqld
# cswch/s: 自愿上下文切换(进程主动让出 CPU,如 IO 等待)
# nvcswch/s: 非自愿上下文切换(时间片用完被强制切换,> 1000 表示 CPU 竞争激烈)

优化措施:

  • nvcswch/s 过高 → CPU 核心数不足,考虑升级或迁移部分进程
  • cswch/s 过高 → IO 密集型应用,优化磁盘性能或使用异步 IO

4. 查看 CPU 中断

# 查看硬件中断统计
cat /proc/interrupts

# 输出示例(部分):
#            CPU0       CPU1       CPU2       CPU3
#   0:        150          0          0          0   IO-APIC   2-edge      timer
#   8:          1          0          0          0   IO-APIC   8-edge      rtc0
#   9:          0          0          0          0   IO-APIC   9-fasteoi   acpi
#  16:   25000000   30000000   28000000   27000000   IO-APIC  16-fasteoi   eth0
#  17:    5000000    6000000    5500000    5300000   IO-APIC  17-fasteoi   ahci[0000:00:1f.2]

# 关注点:
# - eth0(网卡中断)数值过大 → 网络流量高或网卡驱动问题
# - ahci(磁盘中断)数值过大 → 磁盘 IO 频繁

# 查看软中断(softirq)
watch -d -n 1 'cat /proc/softirqs'

# 按 CPU 查看中断分布
mpstat -P ALL 1

# 输出示例:
# 10:30:01 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
# 10:30:02 AM  all   60.25    0.00   15.00    0.75    0.50    3.50    0.00    0.00    0.00   20.00
# 10:30:02 AM    0   65.00    0.00   18.00    1.00    1.00    5.00    0.00    0.00    0.00   10.00
# 10:30:02 AM    1   58.00    0.00   14.00    0.50    0.30    2.20    0.00    0.00    0.00   25.00

# %irq + %soft > 10% 表示中断处理消耗过多 CPU

4. 火焰图分析 (高级)

# 安装 perf 工具
# RHEL/CentOS
yum install perf

# Ubuntu/Debian
apt install linux-tools-$(uname -r) linux-tools-generic

# 采集 CPU 性能数据(采样 30 秒)
perf record -F 99 -a -g -- sleep 30
# -F 99: 采样频率 99Hz
# -a: 所有 CPU
# -g: 记录调用栈
# 输出:perf.data 文件

# 查看采样报告
perf report

# 生成火焰图(需安装 FlameGraph 工具)
git clone https://github.com/brendangregg/FlameGraph.git
perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > cpu-flamegraph.svg

# 在浏览器中打开 cpu-flamegraph.svg
# 宽度 = CPU 时间占比,高度 = 调用栈深度
# 点击可交互查看具体函数耗时

6.2. 内存维度排查

1. 查看整体内存使用

# 查看内存使用概览
free -h

# 输出示例:
#               total        used        free      shared  buff/cache   available
# Mem:           15Gi       8.5Gi       1.2Gi       500Mi       5.8Gi       6.0Gi
# Swap:         8.0Gi       2.0Gi       6.0Gi

# 关键指标:
# total: 物理内存总量
# used: 已使用内存(包含应用 + 缓存)
# free: 真正空闲内存(通常很小,正常现象)
# buff/cache: 文件系统缓存与缓冲区(可被释放)
# available: 可用内存(free + 可释放的 cache)★ 重点关注
# Swap used: SWAP 使用量(> 0 表示内存不足,> 10% 物理内存表示严重不足)

# 实时监控内存变化
vmstat 1

# 输出示例:
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
#  2  0 2048000 1200000 102400 5800000    0   10     0    20 8500 25000 60 15 25  0  0

# 关键列:
# swpd: SWAP 已使用量(字节)
# free: 空闲内存
# buff: 缓冲区内存
# cache: 页缓存内存
# si: 从 SWAP 读入内存的速率(KB/s)(> 0 表示正在使用 SWAP)
# so: 写入 SWAP 的速率(KB/s)(> 0 表示内存压力大)

判断内存瓶颈:

# 计算内存使用率
awk '/MemTotal/ {total=$2} /MemAvailable/ {avail=$2} END {printf "Memory Usage: %.2f%%\n", (total-avail)/total*100}' /proc/meminfo

# 输出:Memory Usage: 62.50%
# < 80%: 正常
# 80-90%: 警告
# > 90%: 严重(可能触发 OOM Killer)

2. 查看进程内存占用

# 按内存使用排序查看前 20 个进程
ps aux --sort=-%mem | head -20

# 输出示例:
# USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
# mysql     1234 35.3 25.2 4567890 2567890 ?      Ssl  Jan10  450:30 /usr/sbin/mysqld
# java      5678 15.2 18.3 6789012 1867890 ?      Sl   Jan09  250:15 java -jar app.jar

# 关键列:
# VSZ (Virtual Memory Size): 虚拟内存大小(包含共享库、未分配页)
# RSS (Resident Set Size): 实际物理内存占用(重点关注)★

# 查看进程详细内存映射
pmap -x 1234

# 输出示例:
# Address           Kbytes     RSS   Dirty Mode  Mapping
# 0000000000400000    1024    1024       0 r-x-- mysqld
# 00007f8a5c000000   65536   32768   16384 rw--- [heap]
# 00007f8a60000000  262144  131072       0 r---- /usr/lib/mysql/plugin/auth_socket.so

# 查看进程内存详细统计
cat /proc/1234/status | grep -E "VmSize|VmRSS|VmSwap"

# 输出示例:
# VmSize:	 4567890 kB  # 虚拟内存
# VmRSS:	 2567890 kB  # 物理内存
# VmSwap:	  150000 kB  # 被 SWAP 的内存(> 0 表示内存不足)

3. 分析内存泄露

# 持续监控进程内存增长趋势
whiletrue; do
date
    ps aux | grep mysqld | grep -v grep | awk '{print "RSS: " $6 " KB"}'
sleep 60
done

# 输出示例:
# 2025-01-15 10:30:00
# RSS: 2567890 KB
# 2025-01-15 10:31:00
# RSS: 2598765 KB  # 增长 30MB
# 2025-01-15 10:32:00
# RSS: 2632456 KB  # 持续增长 → 可能内存泄漏

# 使用 valgrind 检测内存泄漏(开发/测试环境)
valgrind --leak-check=full --log-file=valgrind.log ./your_app

# 生产环境使用 pmap 对比内存映射变化
pmap 1234 > pmap_before.txt
# 等待 10 分钟
pmap 1234 > pmap_after.txt
diff pmap_before.txt pmap_after.txt
# 查找持续增长的内存段([heap] 或匿名映射)

4. 查看 SWAP 使用与优化

# 查看 SWAP 分区信息
swapon -s

# 输出示例:
# Filename				Type		Size	Used	Priority
# /dev/sda2             partition	8388604	2048000	-2

# 查看 SWAP 使用详情
cat /proc/meminfo | grep -i swap

# 输出示例:
# SwapTotal:        8388604 kB
# SwapFree:         6340604 kB
# SwapCached:          1000 kB  # 被缓存的 SWAP 页

# 调整 SWAP 倾向性(临时生效)
# vm.swappiness: 0-100,默认 60
# 0: 尽量不使用 SWAP(除非内存极度不足)
# 10: 推荐值(优先使用内存)
# 60: 系统默认(平衡内存与 SWAP)
# 100: 积极使用 SWAP
sysctl vm.swappiness=10

# 永久生效(/etc/sysctl.conf)
echo"vm.swappiness = 10" >> /etc/sysctl.conf
sysctl -p

# 清空 SWAP(释放被交换出的内存,需谨慎)
# 前提:确保物理内存充足
swapoff -a && swapon -a

5. OOM Killer 日志分析

# 查看 OOM Killer 历史记录
dmesg | grep -i "out of memory"

# 输出示例:
# [1234567.890123] Out of memory: Killed process 5678 (java) total-vm:6789012kB, anon-rss:1867890kB, file-rss:0kB, shmem-rss:0kB
# [1234568.901234] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=java,pid=5678,uid=1000

# 解读:
# - Killed process 5678 (java): 被杀死的进程
# - total-vm: 虚拟内存总量
# - anon-rss: 匿名内存(堆、栈)
# - OOM Score: 每个进程有 oom_score(越高越容易被杀)

# 查看进程 OOM Score
cat /proc/1234/oom_score
# 输出:850(0-1000,数值越大越容易被 OOM Killer 选中)

# 调整进程 OOM Score(降低被杀优先级)
echo -1000 > /proc/1234/oom_score_adj
# -1000 到 1000:-1000 = 永不被杀(慎用),1000 = 优先被杀

# 查看系统内存分配策略
cat /proc/sys/vm/overcommit_memory
# 0: 启发式过量分配(默认)
# 1: 允许过量分配(不推荐)
# 2: 禁止过量分配(严格模式)

6.3 磁盘 IO 维度排查

1. 查看磁盘 IO 统计

# 实时监控磁盘 IO(每秒刷新)
iostat -x 1

# 输出示例:
# Device            r/s     w/s     rkB/s     wkB/s   rrqm/s   wrqm/s  %rrqm  %wrqm r_await w_await aqu-sz rareq-sz wareq-sz  svctm  %util
# sda             150.00  800.00  6000.00  32000.00     0.00     5.00   0.00   0.62   12.50   45.20   3.50    40.00    40.00   8.50  95.60
# sdb              10.00   20.00   400.00   800.00     0.00     0.00   0.00   0.00    2.30    3.50   0.05    40.00    40.00   1.20  3.60

# 关键列:
# r/s, w/s: 每秒读写次数(IOPS)
# rkB/s, wkB/s: 每秒读写数据量(吞吐量)
# r_await, w_await: 平均 IO 等待时间(ms)(< 20ms 正常,> 50ms 慢)
# %util: 磁盘利用率(> 80% 表示 IO 瓶颈)★ 重点关注
# aqu-sz: 平均队列长度(> 1 表示 IO 排队)

# 判断 IO 瓶颈:
# - %util > 80% 且 r_await / w_await > 20ms → 磁盘性能不足
# - IOPS (r/s + w/s) 接近硬件上限:
#   - HDD: 100-200 IOPS
#   - SATA SSD: 50000-90000 IOPS
#   - NVMe SSD: 200000-500000 IOPS

2. 查看进程 IO 占用

# 实时查看 IO 占用最高的进程
iotop -o
# -o: 仅显示有 IO 的进程
# -P: 显示进程而非线程
# -a: 累积 IO 统计

# 输出示例:
# Total DISK READ :      12.50 M/s | Total DISK WRITE :      32.00 M/s
# Actual DISK READ:      10.20 M/s | Actual DISK WRITE:      30.50 M/s
#   TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
#  1234 be/4  mysql      8.50 M/s   25.00 M/s  0.00 % 85.30 % mysqld --defaults-file=/etc/my.cnf
#  5678 be/4  www-data   3.20 M/s    6.50 M/s  0.00 % 12.50 % nginx: worker process

# 查看进程累积 IO 统计
pidstat -d -p 1234 1

# 输出示例:
# 10:30:01      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
# 10:30:02       27      1234   8500.00  25000.00      0.00      85  mysqld
# kB_rd/s: 每秒读取数据量
# kB_wr/s: 每秒写入数据量
# iodelay: IO 延迟(时钟周期)

3. 分析文件系统缓存

# 查看页缓存统计
cat /proc/meminfo | grep -iE "cached|buffers|dirty|writeback"

# 输出示例:
# Buffers:          102400 kB  # 块设备缓冲区
# Cached:          5800000 kB  # 页缓存(文件内容)★
# SwapCached:         1000 kB
# Dirty:            250000 kB  # 脏页(已修改未写入磁盘)
# Writeback:          5000 kB  # 正在回写的脏页

# 关键指标:
# Dirty > 1GB → 大量脏页未刷盘,可能突发 IO 高峰
# Writeback 持续 > 100MB → 磁盘写入慢,检查磁盘性能

# 手动释放页缓存(测试用,生产环境慎用)
# 1: 释放页缓存
# 2: 释放 dentries 和 inodes
# 3: 释放页缓存、dentries 和 inodes
echo 3 > /proc/sys/vm/drop_caches

# 调整脏页刷盘阈值(/etc/sysctl.conf)
vm.dirty_ratio = 10              # 脏页达到物理内存 10% 时阻塞写入(默认 20%)
vm.dirty_background_ratio = 5    # 脏页达到 5% 时后台刷盘(默认 10%)
vm.dirty_expire_centisecs = 3000 # 脏页超过 30 秒强制刷盘(默认 30 秒)
sysctl -p

4. 磁盘健康检查

# 安装 smartmontools
yum install smartmontools  # RHEL/CentOS
apt install smartmontools  # Ubuntu/Debian

# 查看磁盘健康状态
smartctl -H /dev/sda

# 输出示例:
# === START OF READ SMART DATA SECTION ===
# SMART overall-health self-assessment test result: PASSED
# ✅ PASSED: 磁盘健康
# ❌ FAILED: 磁盘有问题,查看详细信息

# 查看磁盘详细信息
smartctl -a /dev/sda

# 关注指标:
# Reallocated_Sector_Ct: 重新分配的扇区数(> 0 表示有坏道)
# Spin_Retry_Count: 磁盘启动重试次数(HDD,> 0 异常)
# Temperature_Celsius: 温度(> 50°C 注意散热)
# Power_On_Hours: 通电时间(评估磁盘寿命)

6.4. 网络维度排查

1. 查看网络连接统计

# 查看网络连接概览
ss -s

# 输出示例:
# Total: 1250
# TCP:   850 (estab 650, closed 100, orphaned 5, timewait 95)
# UDP:   300
# RAW:   0
# FRAG:  0

# 关键指标:
# estab: 已建立连接数
# timewait: TIME_WAIT 状态连接数(过多可能导致端口耗尽)
# orphaned: 孤儿连接(应用已关闭但未被内核回收)

# 查看详细网络统计
netstat -s

# 输出示例(部分):
# Tcp:
#     1234567 active connection openings
#     234567 passive connection openings
#     12345 failed connection attempts
#     5678 connection resets received
#     650 connections established
#     98765432 segments received
#     87654321 segments sent out
#     12345 segments retransmitted  ← 重传次数(关注)
#     50 bad segments received
#     5678 resets sent

# 计算重传率
# 重传率 = segments retransmitted / segments sent out
# 正常 < 1%,> 5% 表示网络质量差

2. 查看进程网络占用

# 安装 nethogs
yum install nethogs  # RHEL/CentOS
apt install nethogs  # Ubuntu/Debian

# 实时查看进程网络带宽占用
nethogs

# 输出示例:
# NetHogs version 0.8.7
#
#   PID USER     PROGRAM                  DEV        SENT      RECEIVED
#  1234 mysql    mysqld                   eth0      25.50 MB/s   12.30 MB/s
#  5678 www-data nginx: worker           eth0       8.20 MB/s    5.60 MB/s
#  9012 root     sshd: root@pts/0        eth0       0.05 MB/s    0.10 MB/s

# 查看进程网络连接详情
ss -tnp | grep 1234

# 输出示例:
# ESTAB  0      0       192.168.1.10:3306     192.168.1.20:45678  users:(("mysqld",pid=1234,fd=25))
# ESTAB  0      0       192.168.1.10:3306     192.168.1.21:56789  users:(("mysqld",pid=1234,fd=26))

3. 分析网络丢包和重传

# 查看网卡统计(丢包、错误)
ip -s link show eth0

# 输出示例:
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
#     link/ether 00:0c:29:12:34:56 brd ff:ff:ff:ff:ff:ff
#     RX: bytes  packets  errors  dropped overrun mcast
#     987654321  9876543  0       120     0       12345
#     TX: bytes  packets  errors  dropped carrier collsns
#     876543210  8765432  0       50      0       0

# 关键列:
# RX dropped: 接收丢包(> 0 表示缓冲区满或驱动问题)
# TX dropped: 发送丢包
# errors: 错误包数量

# 查看 TCP 重传详情
netstat -s | grep -iE "retransmit|timeout"

# 输出示例:
#     12345 segments retransmitted
#     5678 timeouts
#     Fast retransmits: 3456
#     Retransmits in slow start: 2345

# 查看网络队列积压
ss -lnt

# 输出示例:
# State      Recv-Q Send-Q Local Address:Port    Peer Address:Port
# LISTEN     0      128    0.0.0.0:22            0.0.0.0:*
# LISTEN     0      100    0.0.0.0:3306          0.0.0.0:*
# ESTAB      0      0      192.168.1.10:3306     192.168.1.20:45678
# ESTAB      2048   0      192.168.1.10:80       192.168.1.30:56789  ← Send-Q 积压

# Recv-Q: 接收队列(> 0 表示应用处理慢)
# Send-Q: 发送队列(> 0 表示网络发送慢或对端接收慢)

4. 网络延迟与带宽测试

# 测试网络延迟
ping -c 100 192.168.1.20

# 输出示例:
# 100 packets transmitted, 100 received, 0% packet loss, time 99050ms
# rtt min/avg/max/mdev = 0.250/0.580/2.300/0.350 ms

# 关注指标:
# packet loss: 丢包率(应为 0%)
# rtt avg: 平均延迟(< 1ms 理想,< 10ms 正常,> 50ms 慢)
# mdev: 延迟标准差(抖动,越小越稳定)

# 使用 mtr 追踪路由并测试延迟
mtr -r -c 100 192.168.1.20

# 输出示例:
# HOST: localhost              Loss%   Snt   Last   Avg  Best  Wrst StDev
#   1.|-- gateway              0.0%   100    0.5   0.6   0.3   1.2   0.2
#   2.|-- 192.168.1.20         0.0%   100    0.8   1.0   0.7   2.5   0.3

# 测试带宽(需在服务器端启动 iperf3 服务)
# 服务器端:
iperf3 -s

# 客户端:
iperf3 -c 192.168.1.20 -t 30

# 输出示例:
# [ ID] Interval           Transfer     Bitrate         Retr
# [  5]   0.00-30.00  sec  3.50 GBytes   1.00 Gbits/sec  120    sender
# [  5]   0.00-30.00  sec  3.48 GBytes   997 Mbits/sec           receiver

# Retr: 重传次数(应 < 100)
# Bitrate: 带宽(接近网卡速率为正常)

7. 最小必要原理

本小节主要说明 Linux 性能监控核心概念

7.1. CPU 调度原理

Linux 使用 CFS(Completely Fair Scheduler) 调度算法:

  • 每个进程有虚拟运行时间(vruntime),运行时间越少优先级越高
  • 进程状态:R(运行)、S(睡眠)、D(不可中断睡眠,IO 等待)、Z(僵尸)、T(停止)
  • Load Average = 运行队列长度 + 不可中断睡眠进程(D 状态)

  • 1分钟负载:短期突发
  • 5分钟负载:中期趋势
  • 15分钟负载:长期稳定性

7.2. 内存管理机制

虚拟内存:进程看到的内存地址空间(VSZ)

物理内存:实际占用的 RAM(RSS)

页缓存(Page Cache):文件系统缓存,加速文件读写

SWAP:当物理内存不足时,将不活跃页面换出到磁盘

OOM Killer:内存耗尽时,内核根据 oom_score 杀死进程释放内存

7.3. 磁盘 IO 栈

应用程序
    ↓ write() 系统调用
内核页缓存(Page Cache)
    ↓ 脏页刷盘(pdflush/kworker)
IO 调度器(CFQ/Deadline/NOOP)
    ↓
块设备驱动(SCSI/SATA/NVMe)
    ↓
物理磁盘
  • IO 等待(iowait):CPU 等待 IO 完成的时间百分比
  • IOPS:每秒 IO 操作次数(吞吐量指标)
  • 延迟(latency):单次 IO 请求的响应时间

7.4. 网络协议栈

应用程序(socket)
    ↓ send() / recv()
传输层(TCP/UDP)→ 拥塞控制、重传、流量控制
    ↓
网络层(IP)→ 路由、分片
    ↓
数据链路层(Ethernet)
    ↓
物理层(网卡)→ 中断、DMA
  • 重传:丢包或超时导致,影响吞吐量

  • TIME_WAIT:TCP 连接关闭后保持 2MSL(默认 60秒),防止旧连接包干扰新连接

  • 连接队列:SYN 队列(半连接)、Accept 队列(全连接)

8. 可观测性 (监控 + 告警)

8.1. Prometheus + Node Exporter 监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装 Node Exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar -zxvf node_exporter-1.7.0.linux-amd64.tar.gz
cd node_exporter-1.7.0.linux-amd64

# 启动 Node Exporter
./node_exporter &

# 验证指标采集
curl http://localhost:9100/metrics | grep node_cpu

# Prometheus 配置(prometheus.yml)
scrape_configs:
  - job_name: 'linux-server'
    static_configs:
      - targets: ['192.168.1.10:9100']

关键指标:

# CPU 使用率
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 内存使用率
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

# 磁盘 IO 利用率
rate(node_disk_io_time_seconds_total[5m]) * 100

# 网络丢包率
rate(node_network_receive_drop_total[5m]) + rate(node_network_transmit_drop_total[5m])

8.2. Grafana 面板配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
{
  "panels": [
    {
      "title": "CPU 使用率",
      "type": "graph",
      "targets": [
        {
          "expr": "100 - (avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)"
        }
      ],
      "yaxes": [
        {
          "format": "percent",
          "max": 100
        }
      ]
    },
    {
      "title": "Load Average",
      "type": "graph",
      "targets": [
        {
          "expr": "node_load1",
          "legendFormat": "1m"
        },
        {
          "expr": "node_load5",
          "legendFormat": "5m"
        },
        {
          "expr": "node_load15",
          "legendFormat": "15m"
        }
      ]
    },
    {
      "title": "内存使用",
      "type": "graph",
      "targets": [
        {
          "expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes",
          "legendFormat": "Used"
        },
        {
          "expr": "node_memory_MemAvailable_bytes",
          "legendFormat": "Available"
        }
      ],
      "yaxes": [
        {
          "format": "bytes"
        }
      ]
    }
  ]
}

9. 常见瓶颈对照表

症状 瓶颈维度 诊断命令 优化措施
Load Average > CPU核心数 CPU top, mpstat -P ALL 升级CPU/优化代码/进程迁移
%iowait > 30% 磁盘 IO iostat -x, iotop 升级SSD/优化SQL/增加索引
SWAP 使用 > 10% 内存 free -h, vmstat 增加内存/优化应用内存占用
网络重传率 > 5% 网络 netstat -s, ss -ti 检查网线/交换机/MTU配置
进程 D 状态(不可中断睡眠) 磁盘/网络 ps aux | grep " D " 检查NFS挂载/磁盘故障
大量 TIME_WAIT 连接 网络 ss -s, netstat -an 调整内核参数 tcp_tw_reuse

10. 变更与回滚

内核参数优化示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 备份原配置
cp /etc/sysctl.conf /etc/sysctl.conf.bak.$(date +%Y%m%d)

# 性能优化参数(/etc/sysctl.conf)
# 网络优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 10000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 10000 65000

# 内存优化
vm.swappiness = 10
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5

# 文件描述符
fs.file-max = 655350

# 应用配置
sysctl -p

# 验证
sysctl -a | grep -E "somaxconn|swappiness|dirty_ratio"

回滚:

1
2
cp /etc/sysctl.conf.bak.20250115 /etc/sysctl.conf
sysctl -p

11. 最佳实践

  1. 建立性能基线:记录正常状态下的指标值
  2. 分层监控:系统层 → 应用层 → 业务层
  3. 自动化巡检:定时采集性能数据(sar -A)
  4. 火焰图常态化:定期生成CPU/内存火焰图
  5. 容量规划:根据历史趋势预测资源需求
  6. 告警分级:warning / critical / emergency
  7. 演练故障场景:压测、限流、熔断测试
  8. 文档化瓶颈案例:积累排查经验库

12. FAQ

Q1: Load Average 多高算高? A: Load Average / CPU核心数 > 1.0 表示CPU不足。例如4核CPU,Load > 4.0 表示严重瓶颈。

Q2: %iowait 高一定是磁盘慢吗? A: 不一定。也可能是应用IO模式不合理(大量小文件随机读写)。需结合 iostat 的 await 判断。

Q3: 如何判断是CPU密集还是IO密集? A: CPU密集:us% 高,iowait% 低;IO密集:iowait% 高,us% 低。

Q4: SWAP 使用了就一定有问题吗? A: 少量SWAP(< 100MB)可接受,但 si/so(换入换出速率)> 0 表示内存压力大。

Q5: 如何快速定位占用资源最多的进程? A: top 按 Shift+P(CPU排序)/ Shift+M(内存排序)。

Q6: 网络重传率多少正常? A: < 1% 正常,1-5% 可接受,> 5% 需排查网络。

Q7: 如何模拟性能瓶颈测试工具? A: CPU: stress-ng,IO: fio,网络: iperf3

Q8: perf 火焰图看不懂怎么办? A: 宽度 = 时间占比(越宽越耗时),点击可下钻到具体函数。

Q9: 如何监控容器内的性能? A: 使用 docker stats 或 cAdvisor + Prometheus。

Q10: 云主机性能不稳定怎么排查? A: 关注 st%(steal time),> 10% 表示宿主机资源竞争,联系云厂商。

13. 附录: 一键诊断脚本

linux_performance_check.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/bin/bash
# 文件名:linux_performance_check.sh
# 用途:一键诊断 Linux 系统性能瓶颈

echo"==== Linux 系统性能诊断 ===="
echo"诊断时间: $(date)"
echo""

# 1. 系统基本信息
echo"[1/8] 系统信息"
echo"主机名: $(hostname)"
echo"内核版本: $(uname -r)"
echo"CPU 核心数: $(nproc)"
echo"物理内存: $(free -h | awk '/Mem:/ {print $2}')"
echo""

# 2. CPU 使用情况
echo"[2/8] CPU 使用率"
mpstat 1 3 | tail -1
echo""

# 3. Load Average
echo"[3/8] Load Average"
uptime
LOAD=$(uptime | awk -F'load average:''{print $2}' | awk '{print $1}' | sed 's/,//')
CORES=$(nproc)
echo"单核负载: $(echo "scale=2; $LOAD / $CORES" | bc)"
echo""

# 4. 内存使用
echo"[4/8] 内存使用"
free -h
echo""

# 5. 磁盘 IO
echo"[5/8] 磁盘 IO(采样3秒)"
iostat -x 1 3 | tail -n +4 | head -10
echo""

# 6. 网络连接
echo"[6/8] 网络连接统计"
ss -s
echo""

# 7. TOP 进程(CPU)
echo"[7/8] CPU 占用 TOP10 进程"
ps aux --sort=-%cpu | head -11
echo""

# 8. TOP 进程(内存)
echo"[8/8] 内存占用 TOP10 进程"
ps aux --sort=-%mem | head -11
echo""

echo"==== 诊断完成 ===="
echo"建议:"
echo"- Load Average 单核 > 1.0 → CPU 瓶颈"
echo"- Memory Available < 20% → 内存不足"
echo"- Disk %util > 80% → 磁盘 IO 瓶颈"
echo"- Network retrans > 5% → 网络问题"

使用方法:

1
2
chmod +x linux_performance_check.sh
./linux_performance_check.sh > performance_report_$(date +%Y%m%d_%H%M%S).txt

14. 扩展阅读

官方文档:

经典书籍:

  • 《性能之巅》(Systems Performance by Brendan Gregg)
  • 《Linux 性能优化实战》

工具资源:

本文由作者按照 CC BY 4.0 进行授权