02 Linux 系统运维深度

0 阅读6分钟

面试官关注点:不问你 ls 怎么用,问你生产机器慢了怎么定位为什么内核这样设计改过哪些内核参数


一、性能分析方法论

1.1 USE 方法(Brendan Gregg)

对每个资源检查 Utilization(利用率)、Saturation(饱和度)、Errors(错误数)

  • CPU:使用率、运行队列长度、软硬件错误
  • 内存:使用率、swap 频率、OOM kill
  • 磁盘:iops/bw 使用率、队列深度、IO 错误
  • 网络:带宽使用率、丢包/重传、错误包

1.2 RED 方法(服务视角)

  • Rate:请求速率
  • Errors:错误率
  • Duration:延迟

1.3 60 秒快速诊断脚本

uptime                    # 负载趋势
dmesg | tail              # 内核异常(OOM、段错误、驱动报错)
vmstat 1 5                # CPU/内存/swap 整体
mpstat -P ALL 1 5         # 每核 CPU 细分
pidstat 1 5               # 按进程 CPU
iostat -xz 1 5            # 每盘 IO(%util、await、svctm)
free -m                   # 内存细分
sar -n DEV 1 5            # 网卡流量
sar -n TCP,ETCP 1 5       # TCP 错误/重传
top / htop                # 实时进程

二、CPU 深度分析

2.1 CPU 指标解读

指标含义警戒线
%us用户态持续 >70% 需要排查
%sy内核态>30% 可能是系统调用过多、锁争用
%waIO 等待>20% 磁盘瓶颈
%si软中断单核 >30% 可能是网卡收包瓶颈
%st被虚拟化偷走>5% 宿主机超卖
load avg1/5/15 分钟运行队列长度超过 CPU 核数 1-2 倍警戒

2.2 经典排查链路

top (发现 %us 高) → top -H -p <PID> 找热点线程 → printf "%x\n" <TID> 转 16 进制
→ jstack <PID> | grep <十六进制TID> -A 20 (Java) 或 perf top -p <PID> (native)
→ perf record -F 99 -p <PID> -g -- sleep 30 && perf report
→ 生成火焰图 FlameGraph

2.3 软中断优化(网卡密集)

cat /proc/interrupts | grep eth       # 查看中断分布是否均衡
cat /proc/softirqs                    # NET_RX、NET_TX 分布
# 优化:
# 1. RPS/RSS:多队列网卡,把中断绑定到多核
# 2. 关闭 irqbalance,手动 SMP affinity
# 3. 开启 GRO/TSO 减少包处理数
ethtool -l eth0                       # 查看网卡队列数
ethtool -L eth0 combined 8            # 开启 8 队列

2.4 CPU 隔离与绑定

  • isolcpus:内核启动参数隔离核不参与调度,数据面应用独占
  • cgroup cpuset:容器 CPU 绑定
  • taskset / numactl:进程级绑定
  • NUMA 本地性numactl --hardware 查拓扑,跨 NUMA 访存延迟高 1.5-2x

三、内存深度分析

3.1 内存指标与误区

free -m
#               total    used    free    shared  buff/cache   available
# Mem:          32000    20000    2000        500        10000      11000
  • used 高不等于内存紧张,看 available
  • buff/cache 可回收,不要被 used 吓到
  • swap 使用 ≠ 内存不够,可能是长期不活跃页被换出(vm.swappiness 控制积极性)

3.2 查谁在吃内存

ps aux --sort=-rss | head -20         # 按 RSS 排序
smem -k -s uss                        # USS/PSS/RSS 更准确
cat /proc/<pid>/smaps                 # 按内存段查
pmap -x <pid>                         # 进程内存布局
slabtop                               # 内核 slab 缓存(dentry、inode)

3.3 OOM 排查

dmesg -T | grep -i oom                # 查找 OOM killer 日志
# 关键字段:oom_score(被杀优先级)、oom_score_adj(可调整)
# /proc/<pid>/oom_score_adj = -1000 (不被杀) ~ 1000 (优先杀)

# cgroup 内存限制触发 OOM
cat /sys/fs/cgroup/memory/.../memory.oom_control
cat /sys/fs/cgroup/memory/.../memory.usage_in_bytes

3.4 关键内核参数

# /etc/sysctl.conf
vm.swappiness = 10              # 降低 swap 积极性(DB 机器设 1)
vm.overcommit_memory = 1        # 允许过量承诺(Redis 必须)
vm.overcommit_ratio = 80
vm.dirty_ratio = 20             # 脏页上限(触发同步写)
vm.dirty_background_ratio = 10  # 脏页后台刷新阈值
vm.min_free_kbytes = 1048576    # 保留最小空闲,避免突发分配失败
vm.max_map_count = 262144       # ES 必改

3.5 透明大页(THP)

  • DB 场景禁用:Redis、MongoDB、MySQL 官方都建议关闭
  • 动态内存碎片整理会引发延迟毛刺
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

四、磁盘 IO 深度分析

4.1 iostat 核心字段

iostat -xz 1
# r/s, w/s     每秒读写次数(IOPS)
# rkB/s wkB/s  带宽
# await        IO 平均等待时间(ms)  ⚠️ 关键
# svctm        服务时间(已废弃,仅参考)
# %util        设备利用率(SSD 接近 100% 不代表瓶颈,需看 await 和队列)
# aqu-sz       平均队列长度

判断瓶颈:SSD 上 await > 10msaqu-sz > 1 就要警惕;HDD 上 await > 50ms 是瓶颈。

4.2 排查 IO 密集进程

iotop -oPa                # 按进程累计 IO
pidstat -d 1              # 每进程 IO
# 看具体文件
cat /proc/<pid>/io
lsof -p <pid>

4.3 IO 调度器

  • none/noop:SSD/NVMe/云盘推荐(硬件/虚拟化层已优化)
  • mq-deadline:通用 SATA SSD
  • bfq:桌面交互场景
  • cfq:已淘汰
cat /sys/block/vda/queue/scheduler
echo none > /sys/block/vda/queue/scheduler

4.4 文件系统选型

  • ext4:通用稳定,中小文件
  • xfs:大文件、大容量(>16TB)、高并发,推荐生产默认
  • btrfs / zfs:需要快照 / 压缩 / 去重
  • 挂载参数:noatime,nodiratime,nobarrier(带电池的 RAID)

五、网络栈深度

5.1 查看连接与 socket

ss -s                         # TCP 汇总(ESTAB、TIME-WAIT 数量)
ss -antp | awk '{print $1}' | sort | uniq -c  # 按状态统计
ss -antp state time-wait      # 查 TIME_WAIT
netstat -i                    # 网卡错误/丢包
ip -s link                    # 同上,更新

5.2 常见 TCP 问题

TIME_WAIT 过多

# /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1            # 允许复用 TW 套接字(客户端方向)
net.ipv4.tcp_max_tw_buckets = 262144 # TW 上限
# tcp_tw_recycle 4.12+ 内核已移除,不要用

CLOSE_WAIT 堆积:应用层 bug,没 close fd,代码问题。

SYN Flood

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.core.somaxconn = 65535           # accept 队列

端口不够用(outbound)

net.ipv4.ip_local_port_range = 1024 65535

5.3 抓包与链路诊断

tcpdump -i eth0 -nn -s0 -w /tmp/a.pcap 'host 1.2.3.4 and port 80'
wireshark / tshark  分析

# 丢包定位(分层)
ping                  # 三层连通性
mtr -n 1.2.3.4        # 每一跳丢包、延迟
traceroute -T -p 443  # TCP 方式探路
tcping                # TCP 连通性

# 内核丢包统计
nstat -az | grep -i drop
cat /proc/net/snmp    # TCP 错误计数
cat /proc/net/netstat # 扩展统计(ListenOverflows、ListenDrops)
ethtool -S eth0 | grep -i drop   # 网卡层丢包

5.4 BBR 拥塞控制

# 高 RTT、高丢包跨境链路提升明显
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

六、进程与信号

6.1 D 状态进程(不可中断睡眠)

  • 通常卡在内核态(IO 等待、NFS hang、某些 mutex)
  • 不能 kill -9,因为信号处理要回到用户态
  • 排查:
cat /proc/<pid>/stack      # 看内核栈
cat /proc/<pid>/wchan      # 等待什么

6.2 僵尸进程(Z)

  • 父进程没 wait,子进程退出后残留 task_struct
  • 修复:让父进程 wait,或重启父进程(zombie 自动被 init 收养清理)

6.3 文件描述符

ulimit -n                            # 当前限制
lsof -p <pid> | wc -l                # 进程打开的 fd 数
cat /proc/<pid>/limits
# 系统级
cat /proc/sys/fs/file-max            # 系统最大
cat /proc/sys/fs/file-nr             # 已使用

生产必改:/etc/security/limits.conf + systemd 的 LimitNOFILE


七、内核参数生产调优模板

# /etc/sysctl.d/99-production.conf

# --- 文件系统 ---
fs.file-max = 6553560
fs.nr_open = 6553560

# --- 内存 ---
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
vm.overcommit_memory = 1
vm.max_map_count = 262144
vm.min_free_kbytes = 1048576

# --- 网络核心 ---
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 10000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144

# --- TCP ---
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.ip_local_port_range = 1024 65535

# --- 拥塞控制 ---
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# --- 连接跟踪(有 iptables 需要调) ---
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 600

应用:sysctl -p /etc/sysctl.d/99-production.conf


八、现代诊断工具箱(eBPF 时代)

工具用途
bpftrace一行脚本级动态追踪
bcc-toolsexecsnoop, opensnoop, tcpconnect, biosnoop事件级观察
perf采样、计数、tracepoints
ftrace函数级追踪
SystemTap传统(已被 eBPF 取代)

经典使用

# 所有 exec 调用
execsnoop-bpfcc
# 谁打开了这个文件
opensnoop-bpfcc -n nginx
# 新建 TCP 连接
tcpconnect-bpfcc
# 单次 IO 延迟分布
biolatency-bpfcc 10 1
# 自定义:哪个进程 write syscall 最多
bpftrace -e 'tracepoint:syscalls:sys_enter_write { @[comm] = count(); }'

阿里内部自研的 SysAK / SysOM 是基于 eBPF 的诊断平台,了解即可。


九、经典故障排查案例

案例 1:服务器突然变慢

现象:QPS 暴跌,延迟飙升 排查

  1. top 发现 load 很高但 CPU 使用率不高 → 大量 D 状态进程
  2. iostat 显示 %util=100%, await=500ms → 磁盘 IO 瓶颈
  3. iotop 定位某进程在疯狂写
  4. 发现日志 DEBUG 级别没关 + logrotate 失效 结论:日志刷爆磁盘 → 紧急关日志 + 清理 + 修 logrotate

案例 2:TCP 连接建立失败

现象:客户端偶发 connect timeout 排查

  1. netstat -s | grep -i listen 发现 ListenOverflows 持续增长
  2. ss -lnt 看到 accept 队列满(Send-Q = Recv-Q 上限)
  3. net.core.somaxconn = 128(默认)远远不够 结论:调大 somaxconn + 应用 backlog,同时扩容应用实例

案例 3:内存泄漏

现象:应用跑几天 OOM 排查

  1. pmap 发现 anon 段持续增长
  2. Java 应用 → jmap -dump + MAT 分析 → 某 Map 无限增长
  3. Native 内存泄漏 → jemalloc + jeprof,或 bccmemleak 结论:代码修复 + 监控堆/RSS 趋势

案例 4:偶发毛刺

现象:P99 延迟每隔几小时飙一次 排查

  1. 排除 GC → 看到毛刺时 sar -B 发现 pgscand/pgsteal 飙高
  2. 内存回收引发 direct reclaim
  3. 或者 THP defrag 导致 结论:关闭 THP defrag + 调高 min_free_kbytes 预留空间

十、面试高频问答

Q1:load average 很高但 CPU 使用率不高,可能是什么? A:load 统计的是运行队列中**可运行 + 不可中断(D 状态)**进程数,IO 密集或 NFS 卡死也会拉高 load。排查顺序:ps aux | awk '$8~/D/' 看 D 状态进程 → iostat / iotop 定位 IO。

Q2:TIME_WAIT 堆积 10 万个有什么影响?怎么解决? A:

  • 影响:占用端口(本地 port 耗尽)、占内存(每个 TW 几 KB)
  • 解决:
    1. tcp_tw_reuse=1(客户端方向安全)
    2. 应用层使用长连接(HTTP Keep-Alive、连接池)
    3. 调大 tcp_max_tw_buckets,超过直接丢弃
    4. 不要用 tcp_tw_recycle(已移除且会在 NAT 下踩坑)

Q3:Linux 内存回收机制? A:分三层:

  1. 后台回收kswapd 守护进程,触发阈值 low watermark
  2. 直接回收:分配时内存不够,当前进程同步回收(引起延迟)
  3. OOM killer:极端情况,按 oom_score 杀进程 vm.min_free_kbytes 控制水位线,太小容易触发直接回收。

Q4:什么时候用 select、poll、epoll?epoll 的 ET 和 LT 区别? A:

  • select/poll:O(n) 遍历,fd 数量小(<1024)可以
  • epoll:O(1),基于事件回调,Linux 高并发首选
  • LT(水平触发):默认,只要条件满足就持续通知(简单,性能略低)
  • ET(边缘触发):只在状态变化时通知一次,必须一次读/写完(Nginx 使用),搭配非阻塞 IO 和循环读

Q5:/proc 和 /sys 的区别? A:

  • /proc:进程信息 + 内核运行时数据(历史原因混在一起)
  • /sys:sysfs,设备、驱动、内核对象的层次化视图(新设计)
  • 两者都是伪文件系统,内核动态生成

Q6:一个请求从网卡到达到应用的全过程? 简答:

  1. 物理层:网卡收包,DMA 到 ring buffer
  2. 硬中断:触发 CPU 中断,内核调度 NAPI(软中断上下文)
  3. 软中断:协议栈处理 IP → TCP → 放入 socket 接收队列
  4. 唤醒进程epoll_wait 返回
  5. 用户态:应用 read 系统调用拷贝数据到用户空间 可衍生问 零拷贝(sendfile/splice)DPDK/XDPRDMA

十一、必读资源

  • 《Systems Performance》Brendan Gregg 第 2 版
  • 《BPF Performance Tools》Brendan Gregg
  • 《Linux Kernel Development》Robert Love
  • 阿里云内核团队博客 / Alibaba Cloud Linux 文档