前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[043][译]blkio-controller.txt

[043][译]blkio-controller.txt

作者头像
王小二
发布2020-06-08 12:09:08
2K0
发布2020-06-08 12:09:08
举报

前言

Linux之父曾说过read the fucking source code。在学习linux的过程中,我觉得read the fucking document也非常的重要,今天又花了几个小时的时间,翻译了一下blkio-controller.txt,对cgroup如何控制IO有了大概的一个了解,当然有些细节还需要进一步的验证,我会继续努力。

翻译

代码语言:javascript
复制
                Block IO 控制
                ===================
概述
========
cgroup子系统“blkio”实现块io控制器。在存储层次结构中叶节点和中间节点,
似乎需要各种IO控制策略(如比例BW(bandwidth)、最大BW)
计划:为blkio控制器使用基于cgroup的相同管理接口,并基于用户选项在后台切换IO策略。               

目前实现了两个IO控制策略。
第一个是成比例的基于权重时间的磁盘分区策略。它在CFQ中实现。因此
此策略仅在使用CFQ时对叶节点生效。
第二个是一种是限制策略,可用于指定在设备上IO速率上限。
此策略在通用块层中实现,可以是用于叶节点以及更高级别的逻辑设备,如设备映射器。

怎么做
=====
1.带宽比例权分
-----------------------------------------
你可以做一个简单的测试,跑两个运行dd线程在不同的cgroups, 这里就是你能做的。

- 开启Block IO控制
    CONFIG_BLK_CGROUP=y

- 开启group scheduling在CFQ调度算法中
    CONFIG_CFQ_GROUP_IOSCHED=y

- 编译启动进入kernel挂在IO controller (blkio); 参考文档cgroups.txt, 为什么cgroups是必须的?.
    mount -t tmpfs cgroup_root /sys/fs/cgroup
    mkdir /sys/fs/cgroup/blkio
    mount -t cgroup -o blkio none /sys/fs/cgroup/blkio

- 创建两个cgroups
    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

- 创建两个相同文件的大小 (512MB)在同一个硬盘上(file1, file2),启动两个dd线程在不同的cgroup读取文件
    
    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_扇区文件。可以说明磁盘时间(以毫秒为单位),多少个扇区
发送到磁盘。我们提供公平的磁盘时间,所以理想情况下,cgroup的io.disk_时间应与权重成比例。

限制(throttling)/上限策略
-----------------------------
- 开启Block IO控制
    CONFIG_BLK_CGROUP=y

- 开启限制在block layer
    CONFIG_BLK_DEV_THROTTLING=y 

- 挂在IO controller (blkio); 参考文档cgroups.txt, 为什么cgroups是必须的?. 
    mount -t cgroup -o blkio none /sys/fs/cgroup/blkio

- 为root group,指定特定设备上的带宽速率。
  策略格式"<major>:<minor>  <bytes_per_second>"

  echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
  上面会限速1MB/s,root group在8:16设备上发生读操作

- 运行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文件       

Cgroups层级
====================
CFQ和限制(throttling)都支持实现层次结构;但是,如果"sane_behavior"是从cgroup端启用,当前是一个开发选项,并且
不公开。

如果某人创建以下的层级:

            root
            /  \
             test1 test2
            |
             test3

默认的CFQ和限制(throttling)使用"sane_behavior"将处理层次结构正确。有关CFQ层次结构支持的详细信息,
请参阅文档/block/cfq-iosched.txt。对于限制(throttling),所有限制都适用对整个子树,而所有统计数据
都会在cgroup中的task直接生成IO。

如果不从cgroup端启用"sane_behavior",限制(throttling)实际上对待所有组一个级别


                pivot
                 /  /   \  \
            root  test1 test2  test3

各种用户可见的配置选项
===================================
CONFIG_BLK_CGROUP
    - Block IO controller的总开关.

CONFIG_DEBUG_BLK_CGROUP
    - 如果开启这个选项

CONFIG_CFQ_GROUP_IOSCHED
    - 开启CFQ中的分组调度,目前只支持创建一级的组

CONFIG_BLK_DEV_THROTTLING
    - 开启block layer中的块设备的限制(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
      为这个cgroup在设备/dev/sdb (8:16)配置weight=300
      # echo 8:16 300 > blkio.weight_device
      # cat blkio.weight_device
      dev     weight
      8:16    300

      为这个cgroup在设备/dev/sdb (8:0)配置weight=500
      # echo 8:0 500 > blkio.weight_device
      # cat blkio.weight_device
      dev     weight
      8:0     500
      8:16    300

      移除这个cgroup在设备/dev/sdb (8:0)配置的weight
      # 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有竞争关系
      关于细节,请参考文档/block/cfq-iosched.txt。

- blkio.time
    - 分配给每个设备的cgroup的磁盘时间(毫秒)。
      首先两个字段指定设备的主要和次要编号,第三个字段指定分配给组的磁盘时间毫秒。

- blkio.sectors
    - 当前group传输到/从磁盘的扇区数。
      首两个字段指定设备的主要和次要编号,第三个字段指定传输到/从磁盘的扇区数。

- blkio.io_service_bytes
    - 当前group传输到/从磁盘传输的字节数。这些按操作类型进一步划分-读或写、同步或者异步。
      前两个字段指定设备的主要和次要编号,第三个字段指定操作类型和第四个字段指定字节数。

- blkio.io_serviced
    - 当前group发给磁盘的IOs(bio)数。这些按操作类型进一步划分-读或写、同步或者异步。
      前两个字段指定设备的主要和次要编号,第三个字段指定操作类型和第四个字段指定操作的数量。

- blkio.io_service_time
    - 当前group所做的IOs从请求发送到请求完成之间的总时间量。以纳秒计算对闪存设备也有意义。
      当队列深度为1的设备,此时间表示实际服务时间。当队列深度大于1时,这不再是正确的,
      因为请求可能会被无序地送达。这个时间将会包括多个IO的服务时间,当服务不正常时,可能会导致
      io_service_time大于实际运行时间。这个时间按操作类型进一步划分、同步或者异步
      前两个字段指定设备的主要和次要编号,第三个字段指定操作类型,第四个字段指定服务时间(ns)。

- blkio.io_wait_time
    - 当前group的IOs在服务调度队列花费的等待时间,这可能大于总时间已用,因为它是所有io的累计io等待时间。
      它不是衡量cgroup等待的总时间,而是衡量等待其个别IOs的时间。对于队列深度大于1的设备此指标不包括
      等待服务一次所花费的时间IO被发送到设备,但直到它真正得到服务(由于设备)。这是以纳秒为单位的,
      以使它对flash有意义设备也是。这个时间是按操作类型进一步划分,读或写,同步或异步。
      前两个字段指定设备的主要和次要编号,第三个字段指定操作类型
      第四个字段以ns为单位指定io_wait_时间。

- blkio.io_merged
    - 合并到属于这个cgroup的requests的bios/requests总数
      按操作类型进一步划分,读或写,同步或异步

- blkio.io_queued
    - 当前cgroup,在任何给定时刻排队的请求总数。
      按操作类型进一步划分,读或写,同步或异步

- blkio.avg_queue_size
    - 仅会在CONFIG_DEBUG_BLK_CGROUP=y启用调试辅助
      在此期间,此cgroup的平均队列大小。 队列大小事例被用于得到每次此cgroup的队列获取时间间隔

- blkio.group_wait_time
    - 仅会在CONFIG_DEBUG_BLK_CGROUP=y启用调试辅助
      这是cgroup自忙起必须等待的时间(即,从0到排队的1个请求)获取其中一个的时间间隔
      给它的队列。这不同于io_wait_time,后者是该cgroup中每个io在调度程序队列中等待的时间的累计总和。
      以纳秒为单位。 如果在cgroup处于等待态时读取此值, 统计将只报告组等待时间累计到最后一次
      已获取时间间隔,将不包括当前增量

- blkio.empty_time
    - 仅会在CONFIG_DEBUG_BLK_CGROUP=y启用调试辅助
      这是cgroup在未被服务时,在没有任何挂起的请求的情况下花费的时间量, 即, 不包括任何时间
      为cgroup的某个队列花费的空闲时间. 以纳秒为单位,如果在cgroup处于空状态时读取此值,
      统计将只报告在上次有一个挂起的请求之前累积的空时间,而不包括当前的增量

- blkio.idle_time
    - 仅会在CONFIG_DEBUG_BLK_CGROUP=y启用调试辅助
      这是时间的总计,给定cgroup中,IO调度程序比现有请求更好的请求其他队列/cgroup中的而空闲的时间量。
      以纳秒为单位,如果在cgroup处于空闲状态时读取此值,统计将只报告到最后一个空闲周期为止累积的空闲时间,而不包括当前增量。

- blkio.dequeue
    - 仅会在CONFIG_DEBUG_BLK_CGROUP=y启用调试辅助 This
      提供从设备的服务树有关一个组退出队列的次数的统计信息
      前两个字段指定设备的主要和次要编号,第三个字段指定退出队列的次数


- 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
    - 按组分到的磁盘的IOs(bio)数. 这个按操作类型进一步划分、同步或者异步
      首先两个字段指定设备的主要和次要编号,
      第三个字段指定操作类型
      第四个字段指定IOs数

- blkio.throttle.io_service_bytes
    - 按组传输到/从磁盘传输的字节数. 这个按操作类型进一步划分、同步或者异步
      首先两个字段指定设备的主要和次要编号,
      第三个字段指定操作类型
      第四个字段指定字节数


各种策略之间的公共文件
-----------------------------------
- blkio.reset_stats
    - 将int值写入此文件将导致重置这个组的所有统计信息。

CFQ sysfs 调整
=================
/sys/block/<disk>/queue/iosched/slice_idle
------------------------------------------
在更快的硬件上,CFQ可能会很慢,特别是在连续工作负载的情况下。这是因为CFQ在单个队列上空闲,
而单个队列可能不驱动更深的请求队列深度以保持存储繁忙。
在这种情况下可以尝试设置slice_idle=0,这将把CFQ切换到IOPS(每秒IO操作)模式在支持NCQ的硬件。

这意味着CFQ不会在CFQ组和CFQ队列之间空闲,因此能够驱动更高的队列深度,获得更好的吞吐量。
那也意味着cfq在IOPS方面提供了组间的公平性,而不是在磁盘时间条款。

对于SSD设备,可以将这个值设为 0(我自己查的资料)

/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将不空闲对单个组和吞吐量应该提高。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 翻译
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档