cgroup blkio限速仅对Direct I/O生效,而filebeat等日志工具默认使用Buffered I/O,需先用strace或lsof确认O_DIRECT标志;对Buffered I/O应改用ionice、vm.dirty_ratio调优或memory限制。

直接用 cgroup blkio 限制日志搜集进程的磁盘读写吞吐量,关键不在“能不能限”,而在“限得准不准”——它只对 Direct I/O 生效,而多数日志搜集工具(如 filebeat、rsyslog 归档、自定义脚本)默认走 Buffered I/O。所以第一步不是写命令,而是确认 IO 类型。
先判断日志进程是否走 Direct I/O
用 strace 或 lsof -p PID 查看其打开文件时是否带 O_DIRECT 标志:
- filebeat 默认不启用 Direct I/O;需在 output 配置中显式设
flush_interval: 0并配合内核参数优化,但本质仍是 Buffered - rsyslog 的
$ActionFileEnableSync on强制同步写,仍走 PageCache,不属于 Direct I/O - 若你用
dd if=/var/log/app.log of=/backup/ bs=64k oflag=direct或自研工具调用open(..., O_DIRECT),那 blkio 才真正起作用
对 Buffered I/O 日志进程,blkio 无效,需换策略
单纯给这类进程配 blkio.throttle.write_bps_device 基本没效果,因为写操作先进 PageCache,后续刷盘由内核统一调度,blkio 管不到那段路径。此时应组合调控:
- 降低其刷盘优先级:用
ionice -c 3 -p PID(idle class),让内核调度器主动让出 IO 时间片 - 收紧内存缓存压力:调小
vm.dirty_ratio(比如从 20 改为 10),加快脏页回写节奏,避免突发刷盘打满 IO - 限制其可使用的 PageCache 大小:通过
memory.max(cgroup v2)或memory.limit_in_bytes(v1)间接压制缓冲区规模
若确认是 Direct I/O,三步精准限速
适用于定制化日志归档工具、rsync --inplace 同步日志目录、或 tar --use-compress-program="gzip --fast" | dd of=/backup/logs.tar.gz oflag=direct 等场景:
- 查设备号:
ls -l /dev/sda得到brw-rw---- 1 root disk 8, 0→ 设备号是8:0 - 建组并设限:
mkdir /sys/fs/cgroup/blkio/log-collector,然后写入echo "8:0 20971520" > /sys/fs/cgroup/blkio/log-collector/blkio.throttle.read_bps_device(读限 20MB/s)echo "8:0 10485760" > /sys/fs/cgroup/blkio/log-collector/blkio.throttle.write_bps_device(写限 10MB/s) - 绑定进程:
echo $PID > /sys/fs/cgroup/blkio/log-collector/cgroup.procs
验证是否生效,别只看 iotop
iotop 显示的是进程级 IO,但 Buffered I/O 下它反映的是“提交到 PageCache”的速度,不是真实落盘速率。更可靠的验证方式:
- 用
iostat -x 1观察对应设备的svctm(服务时间)、%util和wr_sec/s,看是否稳定在设定值附近 - 压测时用
dd if=/dev/zero of=/mnt/disk/test oflag=direct bs=1M count=1000模拟 Direct I/O 流量,再对比限速前后数值 - 检查
/sys/fs/cgroup/blkio/log-collector/blkio.io_service_bytes统计,确认读写字节数是否被 throttle 截断


















