4.10.5 典型故障与性能瓶颈案例
本节以“现象—定位—根因—处置—预防”的闭环方式沉淀典型故障与性能瓶颈案例,配套可执行命令、安装方法、排错步骤与练习,形成可复用的实战手册。
通用排查闭环原理草图(适用于所有案例)
工具安装(常用诊断工具)
# RHEL/CentOS
yum -y install sysstat perf lsof iotop tcpdump strace
# Ubuntu/Debian
apt-get update
apt-get -y install sysstat linux-tools-common linux-tools-generic lsof iotop tcpdump strace
# 预期效果:可用 top/iostat/pidstat/perf/iotop/tcpdump/strace
案例一:CPU 飙高与负载异常
现象:负载持续升高,响应变慢,CPU 使用率 90%+。
定位命令与解释:
top -o %CPU
# 解释:按 CPU 排序,快速找出高 CPU 进程
pidstat -u 1 -p 1234
# 解释:每 1 秒输出 PID=1234 的线程 CPU 消耗
perf top -p 1234
# 解释:采样热点函数,定位 CPU 热点
处置与验证:
# 临时降级:降低进程优先级
renice +10 -p 1234
# 限制 CPU:cgroup/系统级工具示例
systemd-run --scope -p CPUQuota=50% -p MemoryMax=2G ./app
常见根因:业务线程自旋、GC 频繁、加密/压缩算法过重、死循环。
预防:CPU 基线阈值、线程级监控告警。
排错提示:
- 如果 load average 高但 CPU 不高,优先排查 D 状态阻塞与 IO。
- perf top 看不到业务函数时,检查是否缺少符号或未安装调试包。
练习:
1) 人为制造 CPU 飙高:yes > /dev/null &,用 top 定位并停止。
2) 用 pidstat -u 1 -p 观察 CPU 变化趋势并截图记录。
案例二:内存泄漏与 OOM
现象:内存持续增长,最终触发 OOM Killer。
定位命令与解释:
free -m
# 解释:查看内存与 swap 使用
pmap -x 1234 | tail -n 5
# 解释:查看进程内存映射末尾汇总
grep -i "oom" /var/log/messages
# 解释:定位 OOM Killer 记录
处置与验证:
# 临时释放缓存(仅用于应急)
sync; echo 3 > /proc/sys/vm/drop_caches
# 限制进程最大内存(systemd)
systemctl edit myapp
# 添加:
# [Service]
# MemoryMax=2G
根因:缓存未限制、连接对象未释放、第三方库泄漏。
预防:限制最大堆与缓存、内存曲线告警。
排错提示:
- OOM 日志中查看被杀 PID 与 score。
- 若 swap 持续增长,说明内存压力长期存在。
练习:
1) 用 stress 制造内存压力:stress --vm 1 --vm-bytes 1G --vm-keep。
2) 观察 free -m 与 dmesg | tail 的变化。
案例三:磁盘 IO 瓶颈
现象:iowait 升高,应用响应卡顿。
定位命令与解释:
iostat -x 1 5
# 解释:await、svctm、util 反映 IO 延迟与忙碌度
iotop -oPa
# 解释:按进程汇总 IO,定位写入热点
lsof /data | head
# 解释:查看打开的文件与进程
处置与验证:
# 日志切分(以 nginx 为例)
mv /var/log/nginx/access.log /var/log/nginx/access.log.$(date +%F)
kill -USR1 $(cat /run/nginx.pid)
# 解释:通知 nginx 重新打开日志文件
根因:日志写入过量、随机 IO 激增、磁盘已满或单盘热点。
预防:日志归档策略、IO 基线与容量规划。
练习:
1) 使用 dd if=/dev/zero of=/data/test bs=1M count=500 观察 iostat。
2) 用 iotop 定位 dd 进程并记录 IO 速率。
案例四:网络抖动与连接耗尽
现象:大量超时、连接失败,SYN_RECV 增多。
定位命令与解释:
ss -s
# 解释:汇总 TCP 状态数量
ss -ant | grep SYN-RECV | wc -l
# 解释:统计半连接数量
tcpdump -nn -i eth0 port 80 -c 20
# 解释:抓包查看握手异常
处置与验证:
# 扩大半连接队列
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
# 开启 keepalive
sysctl -w net.ipv4.tcp_keepalive_time=120
根因:半连接队列溢出、NAT/防火墙限制、连接未复用。
预防:连接池规范、监控 TIME_WAIT/SYN_RECV 比例。
练习:
1) 用 ab 或 wrk 造压,观察 ss -s 变化。
2) 调整 tcp_max_syn_backlog 前后对比半连接数。
案例五:系统调用阻塞导致雪崩
现象:大量进程 D 状态,负载飙升但 CPU 不高。
定位命令与解释:
ps -eo pid,state,comm | awk '$2=="D"{print}'
# 解释:列出 D 状态进程
dmesg | tail -n 50
# 解释:查看块设备/NFS 错误
strace -p 1234
# 解释:定位阻塞系统调用
处置与验证:
- 隔离故障盘、切换存储、重建挂载。
- 若 NFS 卡死,尝试卸载 umount -lf /mnt/nfs。
预防:存储健康巡检、多路径与冗余配置。
练习:
1) 人为挂载不存在的 NFS,观察 D 状态。
2) 使用 strace 找到阻塞点并记录。
案例六:中间件瓶颈——MySQL 慢查询与锁等待
原理草图
现象:QPS 下降、连接堆积,慢查询激增。
定位命令与解释:
# 开启慢日志(my.cnf)
[mysqld]
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=1
# 查看锁等待
mysql -e "SHOW PROCESSLIST\G"
mysql -e "SELECT * FROM performance_schema.data_lock_waits\G"
处置与验证:
# 添加索引示例
mysql -e "ALTER TABLE orders ADD INDEX idx_user_id(user_id);"
# 查看执行计划
mysql -e "EXPLAIN SELECT * FROM orders WHERE user_id=123;"
排错提示:
- state 长时间为 Waiting for lock,优先定位长事务。
- 慢 SQL 不是原因而是症状,需结合 CPU/IO。
练习:
1) 创建无索引表并执行慢查询,观察慢日志。
2) 加索引后对比 EXPLAIN。
案例七:Nginx 反向代理 502/499
架构草图
定位命令与解释:
tail -n 100 /var/log/nginx/error.log
# 解释:查看 502/499 相关错误
nginx -T | grep -n "upstream" -n
# 解释:查看上游配置
处置与验证:
# /etc/nginx/conf.d/app.conf
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
client_max_body_size 10m;
排错提示:
- 499 多为客户端主动断开,检查上游耗时。
- 502 多为后端连接失败或超时。
练习:
1) 将上游服务停掉,观察 502。
2) 调整 proxy_read_timeout 并观察错误变化。
案例八:Redis 延迟抖动与主从延迟
架构草图
定位命令与解释:
redis-cli info replication
# 解释:查看主从延迟与复制状态
redis-cli latency doctor
# 解释:诊断延迟来源
redis-cli slowlog get 10
# 解释:查看慢命令
处置与验证:
# 禁止大 key(业务层处理)示例
# 采用 hash 分片:user:{id}:profile
排错提示:
- AOF 重写会导致延迟抖动。
- 大 key 与 KEYS * 会阻塞。
练习:
1) 使用 redis-benchmark -t set,get -n 100000 观察延迟。
2) 人为创建大 key 并观察 slowlog。
案例九:Kafka 生产/消费延迟
架构草图
定位命令与解释:
kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 \
--group mygrp --describe
# 解释:查看消费 lag
tail -n 50 /var/log/kafka/server.log
# 解释:查看 broker 异常
处置与验证:
- 分区不均:调整分区数或重分配。
- ISR 缩小:修复 broker、扩容磁盘。
练习:
1) 创建 topic 并制造 lag,观察 --describe。
2) 关闭一个 broker 观察 ISR 变化。
案例十:Kubernetes 资源抖动
架构草图
定位命令与解释:
kubectl top pod -n default
# 解释:查看 Pod 资源使用
kubectl describe pod myapp
# 解释:查看事件与 OOM/Killed 原因
处置与验证:
# deployment.yaml 资源设置示例
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
排错提示:
- CPU throttling 说明 limits 过低。
- OOMKilled 需优化内存或提升 limits。
练习:
1) 设置过低 limits,观察 Pod 重启。
2) 调整 requests/limits 对比稳定性。
通用复盘与改进清单
1) 记录时间线、影响范围、根因与修复动作。
2) 补充监控指标与阈值、完善告警说明。
3) 完善应急脚本与变更流程,演练恢复步骤。
4) 持续更新典型案例库与排查 Runbook。
综合练习(演练式)
- 设计一次“CPU + IO + 网络”复合故障压测,给出指标阈值与应对流程。
- 用任一中间件(MySQL/Nginx/Redis/Kafka/K8s)制造异常并写出完整排查步骤与恢复方案。