块 I/O 控制器¶
概述¶
cgroup 子系统 “blkio” 实现了块 I/O 控制器。在存储层次结构的叶节点和中间节点都需要各种 I/O 控制策略(如按比例带宽、最大带宽)。计划为 blkio 控制器使用相同的基于 cgroup 的管理接口,并根据用户选项在后台切换 I/O 策略。
一种 I/O 控制策略是节流策略,可用于指定设备上的 I/O 速率上限。此策略在通用块层中实现,可用于叶节点以及更高级别的逻辑设备(如设备映射器)。
操作方法¶
节流/上限策略¶
启用块 I/O 控制器
CONFIG_BLK_CGROUP=y
在块层中启用节流
CONFIG_BLK_DEV_THROTTLING=y
挂载 blkio 控制器(参见 控制组,为什么需要 cgroup?)
mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
为根组在特定设备上指定带宽速率。策略的格式为 “<major>:<minor> <bytes_per_second>”
echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
这将对主次编号为 8:16 的设备上根组发生的读取操作设置 1MB/秒的限制。
运行 dd 读取文件并查看速率是否被限制为 1MB/s
# dd iflag=direct if=/mnt/common/zerofile of=/dev/null bs=4K count=1024
1024+0 records in
1024+0 records out
4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
可以使用 blkio.throttle.write_bps_device 文件设置写入限制。
分层 Cgroup¶
节流实现了分层支持;但是,只有在 cgroup 端启用 “sane_behavior” 时,才会启用节流的分层支持,这目前是一个开发选项,不公开提供。
如果有人创建了如下层次结构
root
/ \
test1 test2
|
test3
使用 “sane_behavior” 的节流将正确处理层次结构。对于节流,所有限制都适用于整个子树,而所有统计信息都位于该 cgroup 中任务直接生成的 I/O 的本地。
在未从 cgroup 端启用 “sane_behavior” 的情况下进行节流,实际上会将所有组视为同一级别,就像如下所示
pivot
/ / \ \
root test1 test2 test3
各种用户可见的配置选项¶
- CONFIG_BLK_CGROUP
块 I/O 控制器。
- CONFIG_BFQ_CGROUP_DEBUG
调试帮助。如果启用此选项,则现在一些额外的统计文件将出现在 cgroup 中。
- CONFIG_BLK_DEV_THROTTLING
在块层中启用块设备节流支持。
cgroup 文件的详细信息¶
按比例权重策略文件¶
- blkio.bfq.weight
指定每个 cgroup 的权重。这是该组在所有设备上的默认权重,除非被每个设备规则覆盖(请参见下面的 blkio.bfq.weight_device)。
目前允许的权重范围是 1 到 1000。有关更多详细信息,请参阅 BFQ(预算公平队列)。
- blkio.bfq.weight_device
指定每个 cgroup 每个设备的权重,覆盖默认组权重。有关更多详细信息,请参阅 BFQ(预算公平队列)。
以下是格式
# echo dev_maj:dev_minor weight > blkio.bfq.weight_device在此 cgroup 中,在 /dev/sdb (8:16) 上配置 weight=300
# echo 8:16 300 > blkio.bfq.weight_device # cat blkio.bfq.weight_device dev weight 8:16 300在此 cgroup 中,在 /dev/sda (8:0) 上配置 weight=500
# echo 8:0 500 > blkio.bfq.weight_device # cat blkio.bfq.weight_device dev weight 8:0 500 8:16 300在此 cgroup 中删除 /dev/sda 的特定权重
# echo 8:0 0 > blkio.bfq.weight_device # cat blkio.bfq.weight_device dev weight 8:16 300- blkio.time
每个设备分配给 cgroup 的磁盘时间,以毫秒为单位。前两个字段指定设备的主次编号,第三个字段指定分配给该组的磁盘时间,以毫秒为单位。
- blkio.sectors
该组传输到/从磁盘的扇区数。前两个字段指定设备的主次编号,第三个字段指定该组传输到/从设备的扇区数。
- blkio.io_service_bytes
该组传输到/从磁盘的字节数。这些字节数根据操作类型(读取或写入、同步或异步)进一步划分。前两个字段指定设备的主次编号,第三个字段指定操作类型,第四个字段指定字节数。
- blkio.io_serviced
该组向磁盘发出的 I/O (bio) 数。这些 I/O 数根据操作类型(读取或写入、同步或异步)进一步划分。前两个字段指定设备的主次编号,第三个字段指定操作类型,第四个字段指定 I/O 数。
- blkio.io_service_time
此 cgroup 完成的 I/O 的请求分派和请求完成之间的总时间。这是以纳秒为单位的,以使其对于闪存设备也有意义。对于队列深度为 1 的设备,此时间表示实际服务时间。当 queue_depth > 1 时,情况不再如此,因为请求可能会乱序服务。这可能会导致给定 I/O 的服务时间包括多个 I/O 的服务时间,乱序服务时可能会导致总 io_service_time > 实际经过时间。此时间根据操作类型(读取或写入、同步或异步)进一步划分。前两个字段指定设备的主次编号,第三个字段指定操作类型,第四个字段以纳秒为单位指定 io_service_time。
- blkio.io_wait_time
此 cgroup 的 I/O 在调度器队列中等待服务所花费的总时间。这可能大于自上次更新以来的总时间,因为它是所有 I/O 的累积 io_wait_time。它不是衡量 cgroup 等待的总时间,而是衡量其各个 I/O 的 wait_time。对于 queue_depth > 1 的设备,此指标不包括将 I/O 分派到设备后但在实际得到服务之前所花费的等待服务的时间(由于设备重新排序请求,这里可能存在时间滞后)。这是以纳秒为单位的,以使其对于闪存设备也有意义。此时间根据操作类型(读取或写入、同步或异步)进一步划分。前两个字段指定设备的主次编号,第三个字段指定操作类型,第四个字段以纳秒为单位指定 io_wait_time。
- blkio.io_merged
合并到属于此 cgroup 的请求中的 bio/请求的总数。此数目根据操作类型(读取或写入、同步或异步)进一步划分。
- blkio.io_queued
在任何给定时刻为此 cgroup 排队的请求总数。此数目根据操作类型(读取或写入、同步或异步)进一步划分。
- blkio.avg_queue_size
仅在 CONFIG_BFQ_CGROUP_DEBUG=y 时才启用的调试辅助。此 cgroup 在其整个存在期间的平均队列大小。每次此 cgroup 的队列之一获得时间片时都会采集队列大小样本。
- blkio.group_wait_time
仅在 CONFIG_BFQ_CGROUP_DEBUG=y 时才启用的调试辅助。这是 cgroup 从繁忙(即,从 0 到 1 个请求排队)到为其中一个队列获取时间片所必须等待的时间。这与 io_wait_time 不同,后者是该 cgroup 中每个 I/O 在调度器队列中等待所花费的时间的累积总和。这是以纳秒为单位的。如果在 cgroup 处于等待(时间片)状态时读取此值,则该统计信息将仅报告累积到上次获取时间片为止的 group_wait_time,并且不包括当前增量。
- blkio.empty_time
仅当 CONFIG_BFQ_CGROUP_DEBUG=y 时启用调试辅助。这是 cgroup 在没有待处理请求且未被服务时所花费的时间,即不包括 cgroup 的任何队列空闲的时间。单位为纳秒。如果在 cgroup 处于空闲状态时读取此值,则该统计信息将仅报告累积到上次有待处理请求时的 empty_time,而不会包括当前的增量。
- blkio.idle_time
仅当 CONFIG_BFQ_CGROUP_DEBUG=y 时启用调试辅助。这是 IO 调度器为给定 cgroup 空闲等待比其他队列/cgroup 的现有请求更好的请求所花费的时间。单位为纳秒。如果在 cgroup 处于空闲状态时读取此值,则该统计信息将仅报告累积到上次空闲期间的 idle_time,而不会包括当前的增量。
- blkio.dequeue
仅当 CONFIG_BFQ_CGROUP_DEBUG=y 时启用调试辅助。这提供了有关组从设备的服务树中出队多少次的统计信息。前两个字段指定设备的主设备号和次设备号,第三个字段指定组从特定设备出队的次数。
- blkio.*_recursive
各种统计信息的递归版本。这些文件显示与其非递归版本相同的信息,但包括来自所有后代 cgroup 的统计信息。
节流/上限策略文件¶
- blkio.throttle.read_bps_device
指定从设备读取的速率上限。IO 速率以字节/秒为单位指定。规则是按设备定义的。以下是格式
echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.throttle.read_bps_device- blkio.throttle.write_bps_device
指定向设备写入的速率上限。IO 速率以字节/秒为单位指定。规则是按设备定义的。以下是格式
echo "<major>:<minor> <rate_bytes_per_second>" > /cgrp/blkio.throttle.write_bps_device- blkio.throttle.read_iops_device
指定从设备读取的速率上限。IO 速率以 IO/秒为单位指定。规则是按设备定义的。以下是格式
echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.throttle.read_iops_device- blkio.throttle.write_iops_device
指定向设备写入的速率上限。IO 速率以 IO/秒为单位指定。规则是按设备定义的。以下是格式
echo "<major>:<minor> <rate_io_per_second>" > /cgrp/blkio.throttle.write_iops_device注意:如果为设备同时指定了带宽和 IOPS 规则,则 IO 将同时受到这两个约束的限制。
- blkio.throttle.io_serviced
该组向磁盘发出的 I/O (bio) 数。这些 I/O 数根据操作类型(读取或写入、同步或异步)进一步划分。前两个字段指定设备的主次编号,第三个字段指定操作类型,第四个字段指定 I/O 数。
- blkio.throttle.io_service_bytes
该组传输到/从磁盘的字节数。这些字节数根据操作类型(读取或写入、同步或异步)进一步划分。前两个字段指定设备的主次编号,第三个字段指定操作类型,第四个字段指定字节数。
各种策略之间的通用文件¶
- blkio.reset_stats
向此文件写入一个整数将导致重置该 cgroup 的所有统计信息。