linux中可通过cgroup v2的io.max控制器实现read_iops限制:先确认启用cgroup v2和config_cgroup_io,再用echo "8:0 rps=100" > /sys/fs/cgroup/logreader/io.max按设备号设读iops上限,最后将进程pid写入cgroup.procs。

在 Linux 中,cgroup 本身不直接提供 read_iops 这样的原生控制器(尤其在 cgroup v1 中),但可通过 blkio 子系统(cgroup v1)或更现代的 io 控制器(cgroup v2)对块设备 I/O 进行限速,包括限制读取操作的 IOPS(每秒 IO 次数)。高频日志读取进程(如 tail -f、grep 日志、日志采集 agent)若未加限制,可能挤占磁盘带宽,影响关键服务。以下是基于实际可用机制的可行方案:
确认使用 cgroup 版本并启用 io 控制器
现代发行版(如 CentOS 8+/RHEL 8+、Ubuntu 20.04+)默认启用 cgroup v2。需确认:
- 运行
mount | grep cgroup,若看到type cgroup2即为 v2; - cgroup v2 的
io控制器支持按设备设置io.max,其中可指定rps(read operations per second)——这正是你所需的read_iops限制; - 确保内核启用了
CONFIG_CGROUP_IO(主流发行版默认开启)。
使用 cgroup v2 设置 per-device 读 IOPS 上限
以限制进程对 /dev/sda 的读 IOPS 为 100 次/秒为例(需 root 权限):
- 创建控制组:
mkdir -p /sys/fs/cgroup/logreader; - 写入设备+限速规则(格式:
<major>:<minor> rps=<value></value></minor></major>):echo "8:0 rps=100" > /sys/fs/cgroup/logreader/io.max(8:0是/dev/sda的主次设备号,用ls -l /dev/sda查看); - 将目标进程加入该组:
echo <pid> > /sys/fs/cgroup/logreader/cgroup.procs</pid>; - 验证:向该组写入任意值后,检查
cat /sys/fs/cgroup/logreader/io.stat中是否出现rqos相关统计,且读请求被节流。
对日志读取进程做自动化管控(推荐实践)
避免手动绑 PID,建议结合 systemd 或启动脚本实现持久化控制:
- 若用 systemd 启动日志工具(如 filebeat、fluent-bit),在 service 文件中添加:
IOReadBandwidthMax=/dev/sda 100(单位:IOPS,systemd 245+ 支持); - 或在启动前通过
cgexec(需安装libcgroup-tools):cgexec -g io:/logreader your-log-reader-command; - 注意:cgroup v2 要求进程及其所有子进程都在同一控制组内,否则子进程可能逃逸限速。
验证与调优要点
单纯设限不等于生效,需实测确认:
- 用
iostat -x 1观察r/s(read requests per second)是否稳定在设定值附近; - 用
dd if=/path/to/big.log bs=4k count=100000 | wc模拟突发读,看是否被平滑压制; - 注意:rps 限制是“设备级”而非“文件级”,若日志分散在多个磁盘,需分别配置;
- 若进程使用 direct I/O(如某些日志 agent 开启
O_DIRECT),部分内核版本下 rps 限速可能不生效,此时需改用bps(带宽)限制作为补充。
不复杂但容易忽略的是设备号匹配和 cgroup 版本一致性。只要路径、设备号、控制器启用三者到位,read_iops 级别的硬性限制就能可靠落地。











