15.11.4 资源瓶颈与性能问题定位

资源瓶颈与性能问题定位#

本节聚焦容器在生产环境中的性能劣化与资源瓶颈定位方法,覆盖 CPU、内存、磁盘 I/O 与网络四类关键资源,并提供可执行的诊断与排错步骤、示例命令与练习。

1. 原理与定位流程(含草图)#

容器资源由 cgroup 进行隔离与限制,性能问题需从宿主机→容器→进程逐层收敛。

文章图片

定位流程(可执行清单)
1. 宿主机是否资源耗尽(CPU/内存/磁盘/网络)
2. 容器是否受限(cgroup 配额)
3. 进程是否异常(高占用、泄漏、阻塞)
4. 变更与流量是否异常(部署/发布/流量峰值)

2. 工具安装与基础准备#

常用性能诊断工具安装(不同发行版请按实际调整):

# Ubuntu/Debian
apt-get update
apt-get install -y sysstat htop iotop iftop iproute2

# CentOS/RHEL
yum install -y sysstat htop iotop iftop iproute
systemctl enable --now sysstat

验证命令是否可用:

iostat -x 1 1
pidstat -u 1 1

3. CPU 瓶颈定位(示例与排错)#

现象:CPU 高、负载升高、响应变慢
关键命令与说明

# 容器 CPU 使用率与限制
docker stats --no-stream

# 宿主机进程 CPU 排序
top -o %CPU

# 进程级 CPU 使用情况(PID 为容器主进程)
pidstat -u -p <pid> 1 5

# cgroup CPU 配额与周期
cat /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_quota_us
cat /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_period_us

示例:定位 CPU 限制过低

# 查看容器限制
docker inspect -f '{{.HostConfig.NanoCpus}}' app1

# 发现 NanoCpus=500000000(0.5核)
# 调整为 2 核
docker update --cpus=2 app1

常见排错点
- 容器 --cpus 过低导致抢占
- 线程池/并发配置过小
- 应用死循环/热点线程

4. 内存瓶颈定位(示例与排错)#

现象:OOM、重启、延迟抖动
关键命令与说明

# 容器内存使用与限制
docker stats --no-stream

# 宿主机内存与交换使用
free -m
vmstat 1 5

# OOM 记录
dmesg | grep -i "oom\|killed process"

示例:发现内存限制过低导致 OOM

# 查看容器内存限制
docker inspect -f '{{.HostConfig.Memory}}' app1

# 将内存限制提升到 2G
docker update --memory=2g app1

JVM 示例(若应用为 Java)

# JVM 推荐设置与容器限制匹配
JAVA_OPTS="-Xms1024m -Xmx1024m -XX:+UseG1GC"

常见排错点
- 内存泄漏或缓存未清理
- JVM 堆设置超过容器限制
- swap 配置不合理导致抖动

5. 磁盘 I/O 瓶颈定位(示例与排错)#

现象:写入延迟、启动慢、日志卡顿
关键命令与说明

# I/O 延迟、队列深度
iostat -x 1 3

# 进程 I/O
iotop -o

# 磁盘空间
df -h

示例:定位日志导致 I/O 突增

# 查看容器日志大小
du -sh /var/lib/docker/containers/<id>/*-json.log

# 配置日志轮转(/etc/docker/daemon.json)
cat > /etc/docker/daemon.json <<'EOF'
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "5"
  }
}
EOF
systemctl restart docker

常见排错点
- 日志暴涨导致 I/O 饱和
- 数据卷与系统盘共享,争用严重
- 存储 IO 性能不足(随机写放大)

6. 网络瓶颈定位(示例与排错)#

现象:连接超时、丢包、吞吐下降
关键命令与说明

# 连接状态与队列
ss -s
ss -ant | head

# 实时流量
iftop -i eth0

# 抓包定位重传/超时
tcpdump -i eth0 -nn port 8080 -c 50

示例:定位连接数耗尽

# 查看 TIME_WAIT 占比
ss -ant | awk '{print $1}' | sort | uniq -c | sort -nr

# 临时优化(谨慎使用)
sysctl -w net.ipv4.tcp_tw_reuse=1

常见排错点
- 端口耗尽/连接数过多
- MTU 不一致导致丢包
- NAT 表耗尽

7. 容器资源限制配置示例(完整可执行)#

# 创建容器并限制 CPU、内存与 I/O
docker run -d --name app1 \
  --cpus=2 \
  --memory=1g \
  --memory-reservation=512m \
  --blkio-weight=500 \
  -p 8080:8080 \
  nginx:1.25

预期效果
- CPU 限制为 2 核
- 内存上限 1G,软限制 512M
- I/O 权重低于默认值

8. 典型问题速查与处理#

  • 高 CPU + 低吞吐:检查线程池、锁竞争、CPU 限制过低
  • 内存持续增长:排查泄漏与缓存,检查 JVM 堆设置
  • 磁盘延迟高:日志爆发、磁盘满、I/O 队列深
  • 网络延迟高:连接数暴增、MTU 不一致、丢包

9. 练习与实操#

  1. CPU 练习
    创建 CPU 限制为 0.2 核的容器,观察 docker statspidstat,再调整为 1 核并比较响应时间。

  2. 内存练习
    --memory=256m 启动容器,运行内存压力工具(如 stress),观察 OOM 记录并调整限制。

  3. I/O 练习
    在容器内持续写入日志,观察 iostat -xiotop,配置日志轮转后验证写入延迟变化。

  4. 网络练习
    使用 abwrk 压测容器服务,观察 ss -s 中连接状态变化,并抓包验证重传情况。