Block IO Controller
===================
总览
========
cgroup子系统 "blkio" 实现了块io控制器。 在存储层次结构中的叶节点以及中间节点处似乎都需要各种类型的IO控制策略(如比例BW,最大BW)。 计划是将相同的基于cgroup的管理界面用于blkio控制器,并根据用户选项在后台切换IO策略。
当前,已实施两种IO控制策略。 第一个是基于比例权重时间的磁盘策略划分。 它在CFQ中实现。 因此,当使用CFQ时,此策略仅对叶节点有效。 第二个是限制策略,可用于指定设备上的IO速率上限。 该策略在通用块层中实现,可以在叶节点以及更高级别的逻辑设备(例如设备映射器)上使用。
如何做
=====
带宽比例权重划分
-----------------------------------------
您可以对在两个不同的cgroup中运行两个dd线程进行非常简单的测试。 这是您可以做的。
-启用块IO控制器 CONFIG_BLK_CGROUP = y -在CFQ中启用组调度 CONFIG_CFQ_GROUP_IOSCHED = y -编译并在内核中启动,并挂载IO控制器(blkio); 请参阅cgroups.txt,为什么需要cgroup ?。 mount -t tmpfs cgroup_root /sys/fs/cgroup mkdir /sys/fs/cgroup/blkio mount -t cgroup -o blkio none /sys/fs/cgroup/blkio -创建两个cgroup mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2 -设置组test1和test2的权重 echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight -在同一磁盘上创建两个大小相同的文件(文件1,文件2,每个文件512 MB),并在不同的cgroup中启动两个dd线程去读取这些文件。 sync echo 3 > /proc/sys/vm/drop_caches dd if=/mnt/sdb/zerofile1 of=/dev/null & echo $! > /sys/fs/cgroup/blkio/test1/tasks cat /sys/fs/cgroup/blkio/test1/tasks dd if=/mnt/sdb/zerofile2 of=/dev/null & echo $! > /sys/fs/cgroup/blkio/test2/tasks cat /sys/fs/cgroup/blkio/test2/tasks
-在宏级别,第一个dd应该先完成。 为了获得更精确的数据,请继续(借助脚本)查看 test1 和 test2 组的 blkio.disk_time 和 blkio.disk_sectors 文件。 这将告诉每个组获得了多少磁盘时间(以毫秒为单位),每个组向磁盘派发了多少个扇区。 我们提供磁盘时间方面的公平性,因此理想情况下 cgroups 的 io.disk_time 应该与权重成比例。
节流/上限策略
-----------------------------
-启用块IO控制器 CONFIG_BLK_CGROUP=y -在块层启用节流 CONFIG_BLK_DEV_THROTTLING=y -挂载blkio控制器(请参阅cgroups.txt,为什么需要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 上面将对 major/minor设备号为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
====================
CFQ和节流策略都实现了对层次结构的支持; 但是,如果从 cgroup 端启用了“sane_behavior”,则启用了节流的层次结构支持,
当前这是开发选项,并且不公开。
如果有人创建了如下的层次结构。
root / \ test1 test2 | test3
默认情况下,CFQ并使用“sane_behavior”进行限制将正确处理层次结构。 有关CFQ层次结构支持的详细信息,请参阅 Documentation/block/cfq-iosched.txt。 对于节流,所有限制都适用于整个子树,而所有统计信息对于该cgroup中的任务直接生成的IO都是本地的。
在没有从cgroup端启用“sane_behavior”的情况下,进行节流实际上会将所有组视为相同级别,就像以下所示。
pivot / / \ \ root test1 test2 test3
各种用户可见的配置选项
==================================
CONFIG_BLK_CGROUP -块IO控制器。 CONFIG_DEBUG_BLK_CGROUP -调试帮助信息。现在,如果启用了此选项,则cgroup中会显示一些其他统计信息文件。 CONFIG_CFQ_GROUP_IOSCHED -在CFQ中启用组调度。 当前仅允许创建1级group。 CONFIG_BLK_DEV_THROTTLING -在块层启用块设备节流支持。
cgroup文件的详细信息
=======================
比例权重策略文件
--------------------------------
-blkio.weight
-指定每个cgroup的权重。 这是所有设备上该组的默认权重,直到且除非被每个设备规则覆盖。(请参阅 blkio.weight_device)。 当前允许的权重范围是10到1000。
-blkio.weight_device
-可以使用此接口为每个设备的每个cgroup指定规则。这些规则将覆盖 blkio.weight 指定的组权重的默认值。
# echo dev_maj:dev_minor weight > blkio.weight_device Configure weight=300 on /dev/sdb (8:16) in this cgroup # echo 8:16 300 > blkio.weight_device # cat blkio.weight_device dev weight 8:16 300 Configure weight=500 on /dev/sda (8:0) in this cgroup # echo 8:0 500 > blkio.weight_device # cat blkio.weight_device dev weight 8:0 500 8:16 300 Remove specific weight for /dev/sda in this cgroup # echo 8:0 0 > blkio.weight_device # cat blkio.weight_device dev weight 8:16 300
-blkio.leaf_weight[_device]
-blkio.weight[_device]的等效项,用于决定与cgroup的子cgroup竞争时给定cgroup中任务的权重。 有关详细信息,请参阅 Documentation/block/cfq-iosched.txt.。
-blkio.time
-每个设备分配给cgroup的磁盘时间(以毫秒为单位)。 前两个字段指定设备的主设备号和次设备号,第三个字段指定分配给组的磁盘时间(以毫秒为单位)。
-blkio.sectors
-此组从磁盘传输或接收的扇区数。前两个字段指定设备的主设备号和次设备号,第三个字段指定组向设备/从设备传输的扇区数。
-blkio.io_service_bytes
-组从磁盘传输的或接收的字节数。这些操作按操作类型进一步划分-读取或写入,同步或异步。 前两个字段指定设备的主要和次要设备号,第三个字段指定操作类型,第四个字段指定字节数。
-blkio.io_serviced
-该组向磁盘发出的IO(bio)数量。 这些操作按操作类型进一步划分-读取或写入,同步或异步。 前两个字段指定设备的主次设备号,第三个字段指定操作类型,第四个字段指定IO的数量。
-blkio.io_service_time
-此cgroup完成的IO的请求分发和请求完成之间的总时间。 这在1ns内对闪存设备也很有意义。 对于队列深度为1的设备,此时间表示实际服务时间。 当 queue_depth > 1时,这不再是正确的,因为可能会无序地处理请求。 这可能会导致给定IO的服务时间在无序提供时包括多个IO的服务时间,这可能导
致总 io_service_time > 实际时间。 该时间还可以通过操作类型进一步划分-读或写,同步或异步。 前两个字段指定设备的主设备号和次设备号,第三个字段指定操作类型,第四个字段指定以ns为单位的io_service_time。
-blkio.io_wait_time
-此cgroup的IO在调度程序队列中等待服务的总时间。这可以大于所花费的总时间,因为它是所有IO的累积 io_wait_time。 它不是衡量 cgroup 等待总时间的方法,而是衡量各个IO的 wait_time 的方法。对于 queue_depth> 1的设备,此指标不包括将IO分配给设备后等待服务所花费的时间,但直到它得到实际服务为止(由于设备对请求的重新排序,因此可能会有时间滞后)。 这在1ns内对闪存设备也很有意义。 该时间还可以通过操作类型进一步划分-读或写,同步或异步。 前两个字段指定设备的主设备号和次设备号,第三个字段指定操作类型,第四个字段指定以ns为单位的 io_wait_time。
-blkio.io_merged
-合并到属于此cgroup的请求的bios/requests总数。 这可以通过操作类型进一步划分-读或写,同步或异步。
-blkio.io_queued
-在任何给定时刻为此cgroup排队的请求总数。 这可以通过操作类型进一步划分-读或写,同步或异步。
-blkio.avg_queue_size
-仅在 CONFIG_DEBUG_BLK_CGROUP = y 时启用的调试辅助。 在此cgroup存在的整个时间内,此cgroup的平均队列大小。 每当此cgroup的队列之一获得时间片时,就对队列大小进行采样。
-blkio.group_wait_time
-仅在 CONFIG_DEBUG_BLK_CGROUP = y 时启用的调试帮助信息。 这是自从cgroup变得繁忙(即请求从0到1进入队列)以来为其队列之一获取时间片所必须等待的时间。 这不同于 io_wait_time,它是该cgroup中每个IO在调度程序队列中等待的时间的累积总数。以纳秒为单位。 如果在cgroup处于等待(用于时间片)状态时读取此内容,则该统计信息将仅报告直到其最后获得时间片为止所累积的 group_wait_time,并且不包括当前增量。
-blkio.empty_time
-仅在 CONFIG_DEBUG_BLK_CGROUP = y 时启用调试辅助信息。 这是cgroup在没有被服务时花费在没有任何未决请求的情况下的时间,即,它不包括花费在cgroup队列之一空闲上的任何时间。 以纳秒为单位。 如果在cgroup处于空状态时读取了此内容,则该统计信息将仅报告直到上一次有待处理请求为止所累积的empty_time,并且将不包括当前增量。
-blkio.idle_time
-仅在 CONFIG_DEBUG_BLK_CGROUP = y 时启用的调试辅助信息。 这是IO调度程序闲置给定cgroup所花费的时间,以期望比来自其他队列/cgroup的现有请求更好的请求。 以纳秒为单位。 如果在cgroup处于空闲状态时读取了此信息,则该统计信息将仅报告直到最后一个空闲时间段为止累积的idle_time,并且将不包括当前增量。
-blkio.dequeue
-仅在 CONFIG_DEBUG_BLK_CGROUP = 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
注意:如果为设备同时指定了BW和IOPS规则,则IO受到两个约束。
-blkio.throttle.io_serviced
-该组向磁盘发出的IO(bio)数量。 这些操作按操作类型进一步划分-读取或写入,同步或异步。 前两个字段指定设备的主编号和次编号,第三个字段指定操作类型,第四个字段指定IO的数量。
-blkio.throttle.io_service_bytes
-组从磁盘传输到磁盘或从磁盘传输的字节数。 这些操作按操作类型进一步划分-读取或写入,同步或异步。 前两个字段指定设备的主要和次要编号,第三个字段指定操作类型,第四个字段指定字节数。
各种政策中的通用文件
-----------------------------------
-blkio.reset_stats
-将int写入此文件将导致重置该cgroup的所有统计信息。
CFQ sysfs可调部分
=================
/sys/block/<disk>/queue/iosched/slice_idle
------------------------------------------
在速度更快的硬件上,CFQ可能会是慢的,尤其是在顺序工作负载下。 发生这种情况是因为CFQ在单个队列上处于空闲状态,并且单个队列可能不会驱动更深的请求队列深度来保持存储繁忙。 在这种情况下,可以尝试设置 slice_idle = 0,然后在支持NCQ的硬件上将CFQ切换为IOPS(每秒IO操作)模式。
这意味着CFQ不会在cfq组的cfq队列之间闲置,因此能够驱动更高的队列深度并获得更好的吞吐量。 这也意味着cfq根据IOPS而不是磁盘时间来提供组之间的公平性。
/sys/block/<disk>/queue/iosched/group_idle
------------------------------------------
如果通过设置 slice_idle = 0禁用单个cfq队列和cfq服务树上的空闲,则会启动group_idle。这意味着CFQ仍将在该组上保持空闲,以尝试在组之间提供公平性。
默认情况下,group_idle 与 slice_idle 相同,并且如果启用 slice_idle 则不执行任何操作。
如果您创建了多个组并将该应用程序放入该组中,而这些应用程序没有驱动足够的IO来保持磁盘繁忙,那么总体吞吐量可能会下降。 在这种情况下,请设置 group_idle = 0,并且CFQ不会在单个组上空闲,并且吞吐量应该会提高。
本文参考链接:https://www.cnblogs.com/hellokitty2/p/14226290.html