Linux 资源紧缺模拟:CPU、内存、磁盘与文件描述符压力测试

1. 引言

在系统运维和性能测试中,模拟资源紧缺是验证系统在极端负载下行为的重要手段。本文介绍如何在 Linux 环境下使用 stress 命令模拟 CPU 和内存压力,使用 fallocate 模拟磁盘占用,并通过调整文件描述符上限来模拟 FD 资源紧缺,最后给出完整的验证与恢复方法。

2. 模拟 CPU 与内存压力

stress 是 Linux 下常用的压力测试工具,可以方便地模拟 CPU、内存、磁盘 I/O 等资源负载。安装方式如下:

bash 复制代码
# CentOS / RHEL
yum install -y stress
Ubuntu / Debian
apt-get install -y stress

模拟 CPU 压力,启动 4 个 CPU 工作进程:

bash 复制代码
stress --cpu 4 --timeout 60s

模拟内存压力,分配 2GB 内存并持续占用:

bash 复制代码
stress --vm 2 --vm-bytes 2G --timeout 60s

也可以同时模拟 CPU 和内存压力:

bash 复制代码
stress --cpu 4 --vm 2 --vm-bytes 1G --timeout 120s

3. 模拟磁盘占用

fallocate 可以快速预分配磁盘空间,用于模拟磁盘资源紧缺。例如创建一个 10GB 的临时文件:

bash 复制代码
fallocate -l 10G /tmp/disk_test.bin

查看磁盘使用情况:

bash 复制代码
df -h /tmp

测试完成后删除临时文件释放空间:

bash 复制代码
rm -f /tmp/disk_test.bin

4. 模拟文件描述符资源紧缺

文件描述符(FD)是 Linux 系统中重要的资源,当进程打开的文件数接近系统上限时,会导致新的文件打开失败。下面演示如何模拟 FD 资源紧缺。

4.1 备份原始文件描述符上限

首先查看并备份系统当前的文件描述符上限:

bash 复制代码
cat /proc/sys/fs/file-max

记录输出的原始值,例如 9223372036854775807,后续恢复时需要用到。

4.2 临时调低文件描述符上限

通过 sysctl 临时将系统文件描述符上限调低到 10000:

bash 复制代码
sysctl -w fs.file-max=10000

4.3 运行消耗脚本

使用 Python 脚本打开约 9000 个文件描述符(目标为上限的 90%)。脚本内容如下:

python 复制代码
import time
target = 9000
fds = []
for i in range(target):
try:
fds.append(open('/dev/null', 'r'))
except IOError:
break
if i % 1000 == 0:
time.sleep(0.01)
print 'Opened %d FDs' % len(fds)
time.sleep(6000)

在后台并行启动 7 个脚本来消耗文件描述符:

bash 复制代码
for i in $(seq 1 7); do
  python2 -c "import time
target = 9000
fds = []
for i in range(target):
    try:
        fds.append(open('/dev/null', 'r'))
    except IOError:
        break
    if i % 1000 == 0:
        time.sleep(0.01)
print 'Opened %d FDs' % len(fds)
time.sleep(6000)" &
done

4.4 验证文件描述符使用率

查看当前系统已分配的文件描述符数量:

bash 复制代码
cat /proc/sys/fs/file-nr

该文件输出三个数值,分别表示已分配文件句柄数、已使用文件句柄数、文件句柄最大值。通过对比已分配数与上限值,可以确认文件描述符的使用率是否达到预期目标。

4.5 恢复文件描述符上限

测试完成后,将文件描述符上限恢复为原始值:

bash 复制代码
sysctl -w fs.file-max=9223372036854775807

同时清理后台运行的 Python 脚本进程:

bash 复制代码
pkill -f "python2 -c"

5. 模拟网络流量与连接资源紧缺

网络资源紧缺同样会影响系统稳定性。下面介绍使用 iperf3 模拟网络流量激增,并演示如何查看主机磁盘 IO 状态、网络延迟与丢包率,以及 TCP 连接数等关键指标。

5.1 使用 iperf3 模拟网络流量激增

iperf3 是常用的网络性能测试工具,可以生成大量 TCP/UDP 流量来模拟网络带宽压力。安装方式如下:

bash 复制代码
# CentOS / RHEL
yum install -y iperf3
Ubuntu / Debian
apt-get install -y iperf3

在一台机器上启动服务端,监听默认端口 5201:

bash 复制代码
iperf3 -s

在另一台机器上作为客户端,向服务端持续发送流量,模拟网络流量激增。例如持续 120 秒并开启 8 个并行连接:

bash 复制代码
iperf3 -c 192.168.1.100 -t 120 -P 8

如需模拟 UDP 流量以观察丢包情况,可使用如下命令:

bash 复制代码
iperf3 -c 192.168.1.100 -u -b 100M -t 120

5.2 模拟磁盘读写压力

用fio命令

安装 fio 的方法取决于你的系统。你之前用的是 CentOS/RHEL 系(yum),直接执行:

bash

复制代码
sudo yum install fio -y

这就是 Oracle 官方文档里针对 CentOS 的标准安装命令。装完后可以用 fio --version 验证。

💡 补充说明

  • 如果是 Ubuntu/Debian :命令是 sudo apt-get update && sudo apt-get install fio -y。

  • 依赖库 :部分系统上 fio 可能依赖 libaio,如果启动时报错,可以补装 sudo yum install libaio libaio-devel -y。

装好后,就可以用之前提到的多 job 命令来压满磁盘写入压力了。

fio 测试读写,写指定文件

搜索到 20 个网页

使用 fio 测试读写并指定文件,核心是通过 --filename 参数明确指定测试文件路径。

📝 基本语法

text

复制代码
fio --name=任务名 --filename=文件路径 --rw=读写模式 --direct=1 --size=文件大小 --runtime=测试时长 --time_based

💡 关键参数说明

参数 说明
--filename 指定测试文件路径。支持文件、裸盘,多个文件用冒号分隔,如 /dev/vda:/dev/vdb
--rw 读写模式:read(顺序读)、write(顺序写)、randread(随机读)、randwrite(随机写)、randrw(随机混合)
--direct=1 绕过系统缓存,直接写入磁盘,测试更真实
--size 测试文件大小,如 2G。若指定已有文件,size 可省略
--time_based 配合 --runtime 使用,让 fio 在指定时间内持续运行,而不是写完文件就结束
--numjobs 并发量

🧪 常用命令示例

顺序写测试

fio --name=write-test --filename=/root/fio_test.bin --rw=write --bs=10M --direct=1 --size=2G --numjobs=8 --time_based --runtime=6000

  • --numjobs=4:4 个并发写任务,压力更大

  • --group_reporting:汇总报告,方便查看整体性能

随机写测试

bash

复制代码
fio --name=randwrite-test --filename=/root/fio_test.bin --rw=randwrite --bs=1M --direct=1 --size=2G --time_based --runtime=600

小块随机写更能压 IOPS。

混合读写测试

bash

复制代码
fio --name=randrw-test --filename=/root/fio_test.bin --rw=randrw --rwmixread=70 --bs=4k --direct=1 --size=2G --time_based --runtime=600
  • --rwmixread=70:70% 读,30% 写

顺序读测试

fio --name=read-test --filename=/root/fio_test.bin --rw=read --bs=1M --direct=1 --size=2G --numjobs=4 --time_based --runtime=600 --group_reporting

⚠️ 注意事项

文件路径选择 :不要用 /tmp ,因为你的 /tmp 是 tmpfs(内存盘),测不出磁盘性能。建议用 /root/ 或专门的数据目录,确保是真实物理磁盘。

写测试会破坏数据 :如果对裸盘做写测试(如 --filename=/dev/vdb),会清空该设备上的所有数据,务必确认目标盘无有用数据。

--size 与已有文件 :如果指定的文件已存在且大小固定,--size 可省略;如果文件不存在,fio 会创建并填充到指定大小。

停止与清理 :--time_based --runtime=600 会在 600 秒后自动停止。测试完成后,生成的测试文件需要手动删除:

bash

复制代码
rm -f /root/fio_test.bin
用 timeout 强制限时(最简洁)

timeout 命令可以让任意命令运行指定秒数后自动终止:

复制代码
# 持续写 6000 秒
timeout 6000 dd if=/dev/zero of=/root/disk_io_test.bin bs=1M count=600000000 conv=fdatasync
复制代码
# 持续读 6000 秒(绕过缓存)
timeout 6000 dd if=/root/disk_io_test.bin of=/dev/null bs=1M iflag=direct

注意:count 要设得足够大(比如 100000),否则 dd 会在 600 秒之前就写完退出,timeout 就失去意义了。上面的 count=100000 意味着最多写 100000MB,实际会被 timeout 在 600 秒时截断。

用 while 循环控制时长(更灵活)

bash

复制代码
# 持续写 600 秒
bash 复制代码
end=$((SECONDS+600))
while [ $SECONDS -lt $end ]; do
    dd if=/dev/zero of=/root/disk_io_test.bin bs=1M count=2048 conv=fdatasync
done
复制代码
# 持续读 600 秒
bash 复制代码
end=$((SECONDS+600))
while [ $SECONDS -lt $end ]; do
    dd if=/root/disk_io_test.bin of=/dev/null bs=1M iflag=direct
done

同时压读和写(并行)

如果你想同时制造读、写压力,可以把两个循环放到后台并行:

bash 复制代码
# 先准备一个文件供读取(如果还没有)
dd if=/dev/zero of=/root/disk_io_test.bin bs=1M count=2048 conv=fdatasync

# 写压力
end=$((SECONDS+600))
while [ $SECONDS -lt $end ]; do
    dd if=/dev/zero of=/root/disk_io_test_write.bin bs=1M count=2048 conv=fdatasync
done &

# 读压力
end=$((SECONDS+600))
while [ $SECONDS -lt $end ]; do
    dd if=/root/disk_io_test.bin of=/dev/null bs=1M iflag=direct
done &

wait

关键参数说明

参数 作用
if=/dev/zero 无限零数据源,用于写测试
of=/dev/null 黑洞,读出的数据丢弃,用于读测试
bs=1M 每次读写 1MB
count=N 读写 N 个块(总大小 = bs × count)
conv=fdatasync 写完后强制刷盘,确保真实写入物理磁盘
iflag=direct 读时绕过 page cache,直接读物理磁盘
bash 复制代码
stress -d 4 --hdd-bytes 1G -t 600

在压测期间,可以使用 iostat 观察磁盘 IO 是否成为瓶颈。安装 sysstat 后执行:

bash 复制代码
# CentOS / RHEL
yum install -y sysstat
Ubuntu / Debian
apt-get install -y sysstat

每隔 2 秒刷新一次磁盘 IO 状态,共输出 5 次:

bash 复制代码
iostat -x 2 5

重点关注 %util(设备利用率)、await(平均 IO 等待时间)和 r/s、w/s(每秒读写次数)等指标,判断磁盘是否处于高负载状态。

5.3 模拟网络延迟与丢包

iptable方式
复制代码
# 模拟本机发出的包,随机丢弃 5%
sudo iptables -A OUTPUT -m statistic --mode random --probability 0.05 -j DROP

# 模拟发往本机的包(入向),随机丢弃 5%
sudo iptables -A INPUT -m statistic --mode random --probability 0.05 -j DROP

针对特定源 IP 丢包(入向)

bash

复制代码
# 丢弃来自 10.11.55.83 的包,概率 5%
sudo iptables -A INPUT -s 10.11.55.83 -m statistic --mode random --probability 0.05 -j DROP

针对特定目标 IP 丢包(出向)

bash

复制代码
# 丢弃发往 10.11.55.83 的包,概率 5%
sudo iptables -A OUTPUT -d 10.11.55.83 -m statistic --mode random --probability 0.05 -j DROP
tc方式

查询网卡

bash 复制代码
ip -br link

所有网络

针对 ens3 模拟延迟和丢包

模拟 200ms 延迟 + 5% 丢包:(建议指定某个ip的流量或者指定过期时间)

复制代码
sudo tc qdisc add dev ens3 root netem delay 200ms loss 5%

加规则,并让它在 300 秒(5 分钟)后自动删除

sudo tc qdisc add dev ens3 root netem delay 200ms loss 5% && (sleep 300 && sudo tc qdisc del dev ens3 root) &

命令解释:

  • &&:规则添加成功后,才启动后面的定时任务。

  • (sleep 300 && ...):子 shell 里先睡 300 秒,醒来后执行删除。

  • 末尾 &:把整个定时任务放到后台,不阻塞当前终端。

这样即使你 SSH 断了,5 分钟后网络也会自动恢复。

指定固定ip丢包

如果只想影响访问某个 IP 的流量,而不是全部,可以结合 filter:

只对目标 IP 10.11.55.83 生效

bash 复制代码
sudo tc qdisc add dev ens3 root handle 1: prio && \
(sleep 300 && sudo tc qdisc del dev ens3 root) & \
sudo tc qdisc add dev ens3 parent 1:1 handle 10: netem delay 200ms loss 5% && \
(sleep 300 && sudo tc qdisc del dev ens3 root) & \
sudo tc filter add dev ens3 protocol ip parent 1:0 prio 1 u32 match ip dst 10.11.55.83 flowid 1:1 && \
(sleep 300 && sudo tc qdisc del dev ens3 root) &

或者

bash 复制代码
sudo tc qdisc add dev ens3 root handle 1: prio && \
sudo tc qdisc add dev ens3 parent 1:1 handle 10: netem delay 200ms loss 5% && \
sudo tc filter add dev ens3 protocol ip parent 1:0 prio 1 u32 match ip dst 10.11.55.83 flowid 1:1 && \
(sleep 300 && sudo tc qdisc del dev ens3 root) &

查看已添加的规则:

bash

复制代码
tc qdisc show dev ens3

恢复(清除规则):

bash

复制代码
sudo tc qdisc del dev ens3 root

5.4 模拟 TCP 连接数激增

使用 hping3 可以快速建立大量 TCP 连接,用于模拟高并发连接场景。安装方式如下:

bash 复制代码
# CentOS / RHEL
yum install -y hping3
Ubuntu / Debian
apt-get install -y hping3

向目标主机持续发起 SYN 请求,模拟大量半开连接:

bash 复制代码
hping3 -S -p 80 --flood 192.168.1.100

如需模拟大量完整 TCP 连接,可结合 iperf3 开启多个并行连接:

bash 复制代码
iperf3 -c 192.168.1.100 -t 120 -P 8

在压测期间,可以使用 ss 命令查看当前系统的 TCP 连接状态和数量。统计所有 TCP 连接数:

bash 复制代码
ss -s

查看处于 ESTABLISHED 状态的连接数:

bash 复制代码
ss -t state established | wc -l

也可以按连接状态分类统计,观察 SYN-SENT、TIME-WAIT 等状态的连接数量:

bash 复制代码
ss -tan | awk '{print $1}' | sort | uniq -c

在压测期间,TCP 连接数和各状态数量会明显上升,可用于验证系统在高并发连接下的表现。

5.5 恢复与清理

测试完成后,停止 iperf3 和 hping3 进程:

bash 复制代码
pkill -f iperf3
pkill -f hping3

移除网络延迟和丢包模拟规则:

bash 复制代码
tc qdisc del dev eth0 root

确认网络流量恢复正常,延迟和丢包率回到基线水平,TCP 连接数回落。

5.3 查看网络延迟与丢包率

使用 ping 命令可以快速查看网络延迟和丢包率。持续发送 100 个数据包并统计结果:

bash 复制代码
ping -c 100 192.168.1.100

输出中的 time 字段表示往返延迟,packet loss 字段表示丢包率。在 iperf3 压测期间执行 ping,可以对比观察网络拥塞对延迟和丢包的影响。

5.4 查看 TCP 连接数

使用 ss 命令可以查看当前系统的 TCP 连接状态和数量。统计所有 TCP 连接数:

bash 复制代码
ss -s

查看处于 ESTABLISHED 状态的连接数:

bash 复制代码
ss -t state established | wc -l

也可以按连接状态分类统计,观察 SYN-SENT、TIME-WAIT 等状态的连接数量:

bash 复制代码
ss -tan | awk '{print $1}' | sort | uniq -c

在 iperf3 压测期间,TCP 连接数和各状态数量会明显上升,可用于验证系统在高并发连接下的表现。

5.5 恢复与清理

测试完成后,停止 iperf3 服务端和客户端进程:

bash 复制代码
pkill -f iperf3

确认网络流量恢复正常,延迟和丢包率回到基线水平,TCP 连接数回落。

5. 总结

本文介绍了在 Linux 环境下模拟资源紧缺的完整方法:使用 stress 模拟 CPU 和内存压力,使用 fallocate 模拟磁盘占用,通过临时调低 fs.file-max 并运行 Python 脚本模拟文件描述符资源紧缺。这些方法可以帮助运维人员验证系统在资源受限情况下的行为,为容量规划和故障演练提供依据。测试完成后务必恢复原始配置,避免影响生产环境。

相关推荐
酒神dnspup1 小时前
多地区网站可用性监控怎么做?DNSPup 从基线到告警的完整实战
运维·ios·云计算·iphone·dns·网络监控
等我调个Bug2 小时前
Linux基本指令
linux·服务器
在角落发呆10 小时前
工具配置备份步骤:从手动备份到自动化方案
运维·windows·自动化
_upupup10 小时前
Linux的调试工具——gdb/cgdb
linux·服务器
百度一下吧11 小时前
Nginx 使用手册:从安装配置到实战部署
运维·nginx
JeJe同学11 小时前
Docker镜像导入、容器启动
linux·运维·docker
Jason_zhao_MR11 小时前
Linux与实时控制如何兼得
linux·嵌入式硬件·机器人·工业控制
回眸&啤酒鸭11 小时前
【回眸】自动化白盒测试落地实战指南
运维·自动化·log4j
闲云野鹤在人间12 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算