• [原] Cgroup CPU, Blkio 测试


    关于Cgroup的简单测试


    简单介绍Cgroup

    (如果对cgroup熟悉可以忽略)
    一般情况下,cgroup挂载到一个虚拟文件目录,然后可以通过文件系统的API对其操作。

    ># mount | grep cgroup 可以查看mount point

    (debian) /sys/fs/cgroup/
    (redhat) /cgroup/
    

    以下非特殊说明,均以ubuntu12.04(3.5.0-23-generic) 为准
    如果没有,安装方式
    ># apt-get install cgroup-bin
    ># yum -y install libcgroup

    可以在 /proc/cgroups 下面看到目前有哪些子系统以及他们的使用情况

    root@vm-222:/sys/fs/cgroup/blkio# cat /proc/cgroups 
    #subsys_name	hierarchy	num_cgroups	enabled
    cpuset	9	1	1
    cpu	10	10	1
    cpuacct	11	1	1
    memory	12	1	1
    devices	13	1	1
    freezer	14	1	1
    blkio	15	2	1
    perf_event	16	1	1
    

    在 /sys/fs/cgroup/ 目录下可以看到如下子系统, 这是系统默认挂载方式,也是推荐的方式。

    zhangbo3@vm-222:/sys/fs/cgroup$ ll
    total 0
    drwxr-xr-x 10 root root 200 Aug 31 23:06 ./
    drwxr-xr-x  6 root root   0 Aug 31 23:14 ../
    drwxr-xr-x  2 root root   0 Aug 31 23:06 blkio/
    drwxr-xr-x  2 root root   0 Sep  6 10:22 cpu/
    drwxr-xr-x  2 root root   0 Aug 31 23:06 cpuacct/
    drwxr-xr-x  2 root root   0 Sep  6 10:22 cpuset/
    drwxr-xr-x  2 root root   0 Aug 31 23:00 devices/
    drwxr-xr-x  2 root root   0 Au  31 23:06 freezr/
    drwxr-xr-x  2 root root   0 Aug 31 23:06 memor/
    drwxr-xr-x  2 root root   0 Aug 31 23:06 perf_event/
    

    也可以将 CPU, MEMORY 子系统都挂载到一个目录下.
    mount -t cgroup -o cpu,memory cpu_mem_cg /sys/fs/cgroup/cpu_mem_cg

    但是当CPU子系统已经被挂载过一次之后,就不能再挂载到第二个目录。

    >#mount -t cgroup -o cpu,memory cpu_mem_cg /sys/fs/cgroup/cpu_mem_cg
    提示错误如下:
    >#mount: /sys/fs/cgroup/cpu_mem_cg already mounted or /sys/fs/cgroup/cpu_mem_cg busy
    

    子系统文件介绍,以cpu子系统为例:

    cpu
    ├── cgroup.clone_children
    ├── cgroup.event_control
    ├── cgroup.procs
    ├── cpu.cfs_period_us
    ├── cpu.cfs_quota_us
    ├── cpu.rt_period_us
    ├── cpu.rt_runtime_us
    ├── cpu.shares
    ├── cpu.stat
    ├── notify_on_release
    ├── release_agent
    └── tasks
    
    

    tasks 里面包含了当前进程,默认安装cgroup后,当前所有系统进程都会纳入cgroup管理,并且被加入到cgroup 根目录下,所有值为cgroup默认值,调度策略也使用完全公平调度.

    cat tasks
    可以看到所有进程.

    cgroup 采用层级管理方式,可以在cpu子系统下面直接新建目录。
    >#mkdir test
    在test/ 目录下面,会基础根目录的所有属性,但是不包括tasks.
    可以调整test/ 目录下面的cpu.* 的值对其设置,比如设置 cpu.shares=100
    >#echo 100 > cpu.shares
    所有tasks里面的pid都会在这个cgroup的管理下, 按照cpu.shares=100的值作为系统调度.

    测试及验证

    此次测试只针对CPU和blkio子系统,CPU用来限制CPU调度,blkio用来限制块设备IO调度

    测试点

    - 查看cpu.shares值是否符合调度预期
    - mysql进程cpu调度是否符合预期
    - 磁盘IO调度是否符合预期

    实际测试结果

    cpu.shares值是否符合预期

    cpu.shares 值作为CPU的子系统的全局调度策略,为某个group设置cpu.shaes值后,会按照系统当前所有shares值为其分配一定权重,默认一个group最大值为1024, 这是个相对值, 比如group1, group2 的shares值同为100,他们应该获取相同的CPU时间片, 如果group1 设置为100,group2 设置为200,则group2的时间片应该是group1的两倍.

    以一个会占据单核所有CPU的进程为例:

    #include <stdlib.h>
    #include <stdio.h>
    int main(){
        volatile float a;
        while(1) {
            a = 88888.8 * 88888.78;
        }
        return ;
    }
    

    默认所有进程已经加入cgroup豪华午餐.
    由于是双核机器,开两个程,完全占据所有CPU.

    PID  USER   PR  NI VIRT RES   SHR  S      %CPU %MEM  TIME+ COMMAND  
    39707 zhangbo3  20   0  4156  348  272 R   99  0.0   0:13.88 crazy  
    39863 zhangbo3  20   0  4156  352  272 R   99  0.0   0:36.14 crazy  
    

    四个进程

    39863 zhangbo3  20   0  4156  352  272 R   48  0.0   1:38.10 crazy  
    39707 zhangbo3  20   0  4156  348  272 R   46  0.0   3:27.95 crazy  
    40124 zhangbo3  20   0  4156  352  272 R   43  0.0   0:05.55 crazy 
     4025 zhangbo3  20   0  4156  352  272 R   46  0.0   0:05.70 crazy
    

    默认权值是1024的cgroup,进程几乎是平分CPU.

    现将39863 39707 两个进程加入到test group, 并设置其cpu.shares=512
    echo 39863 >> tasks
    echo 39707 >> tasks
    echo 512 >> cpu.shares

    查看当前cpu利用率

    40124 zhangbo3  20   0  4156  352  272 R   63  0.0   3:12.10 crazy  
    40125 zhangbo3  20   0  4156  352  272 R   61  0.0   3:12.02 crazy  
    39863 zhangbo3  20   0  4156  352  272 R   34  0.0   4:28.27 crazy  
    39707 zhangbo3  20   0  4156  348  272 R   32  0.0   6:12.77 crazy  
    

    可以看到, 39863 39707 两个进程的CPU 使用率基本是前两个的一半,完全符合预期有木有.

    mysql进程cpu调度是否符合预期

    将两个mysql实例加入到统一group下,为其设置cpu.shares=500
    利用mysqlslap 对两个实例小小压测一下.
    ps:针对CPU的压测,需要将CPU都压满才能体现cpu.shares的值的分配,如果是空载情况下,所有group都会最大限度的利用CPU.

    User time 6.66, System time 13.08
    Maximum resident set size 9548, Integral resident set size 0
    Non-physical pagefaults 26115, Physical pagefaults 0, Swaps 0
    Blocks in 0 out 0, Messages in 0 out 0, Signals 0
    Voluntary context switches 253951, Involuntary context switches 5412
    
    User time 6.57, System time 13.20
    Maximum resident set size 9536, Integral resident set size 0
    Non-physical pagefaults 26080, Physical pagefaults 0, Swaps 0
    Blocks in 0 out 0, Messages in 0 out 0, Signals 0
    Voluntary context switches 255336, Involuntary context switches 4518
    
    

    可以观察到两者的Involuntary context switches值相差不大


    将两个mysql 实例加入到不同的group下,分别为其设置cpu.shares=500, 1000

    User time 12.07, System time 17.12
    Maximum resident set size 150872, Integral resident set size 0
    Non-physical pagefaults 938774, Physical pagefaults 0, Swaps 0
    Blocks in 0 out 0, Messages in 0 out 0, Signals 0
    Voluntary context switches 227545, Involuntary context switches 10615
    
    User time 12.01, System time 18.79
    Maximum resident set size 134212, Integral resident set size 0
    Non-physical pagefaults 1087038, Physical pagefaults 0, Swaps 0
    Blocks in 0 out 0, Messages in 0 out 0, Signals 0
    Voluntary context switches 227556, Involuntary context switches 6800
    

    可以观察到Involuntary context switches值基本符合预期

    磁盘IO调度是否符合预期

    分别将磁盘blkio.weight 设置为 500
    dd if=/dev/zero of=/data2/dd.test bs=8k count=1024000
    产生两个8.4G的文件
    产生如下IO调度分配结果

    1024000+0 records in
    1024000+0 records out
    8388608000 bytes (8.4 GB) copied, 84.7144 s, 99.0 MB/s
    
    1024000+0 records in
    1024000+0 records out
    8388608000 bytes (8.4 GB) copied, 81.2984 s, 103 MB/s
    

    看似符合预期,于是进行下一步
    将进程1的IO权值设置为1000, 进程2的权值设置为100
    可以看到两者并无差别,不符合我们的预期,是我打开的方式不对么?

    4000+0 records in
    4000+0 records out
    4194304000 bytes (4.2 GB) copied, 5.292 s, 70.7 MB/s
    
    4000+0 records in
    4000+0 records out
    4194304000 bytes (4.2 GB) copied, 60.3834 s, 69.5 MB/s
    

    因为需要使用完全公平调度,于是设置io调度方式为cfq

    echo cfq > /sys/block/<divice-name>/queue/scheduler
    

    在cgroup文档里面有这么一个提示:

    blkio子系统只针对非buffered IO或者read IO起作用.
    使用直接IO方式启动DD

    dd if=/dev/zero of=/data/dd.test oflag=direct,nonblock bs=1M count=4000
    

    将buffer刷到磁盘,并清掉cache

    sync
    echo 3 > /proc/sys/vm/drop_caches
    

    观察到IO调度符合预期.

    8192000+0 records in
    8192000+0 records out
    4194304000 bytes (4.2 GB) copied, 35.9584 s, 117 MB/s
    
    root@ip-172-17-6-225:/tmp# cat cgroup2.log 
    4000+0 records in
    4000+0 records out
    4194304000 bytes (4.2 GB) copied, 97.82 s, 42.9 MB/s
    

    因为进程1提前结束,所以会让出一部分时间片给进程2,但是从iotop来看,同时运行的情况下IO调度是负荷预期的.

    总结使用BLKIO子系统必须满足以下几个条件:

    1. 默认系统调度方式为CFQ, 完全公平调度
    2. 内核编译宏 CONFIG_BLK_CGROUP=y CONFIG_CFQ_GROUP_IOSCHED=y
    3. 必须是非buffered 写 IO
    

    总结

    测试过程中使用到的命令:

    mysql 压力测试
    mysqlslap -uxxx -pxxx -P 6810 -h127.0.0.1 --concurrency=200 --iterations=1 --auto-generate-sql --number-of-queries=20000 --debug-info  --create-schema='test2' --auto-generate-sql-load-type=mixed
    
    dd 磁盘压测
    dd if=/dev/zero of=/data/dd.test oflag=direct,nonblock bs=1M count=4000
    
    iotop 查看IO情况
    

    本次测试针对CPU和IO调度都做了相应的测试,调度参数符合预期.

    针对cgroup对MySQL的管理方案:

    1. 限制 CPU 使用,每个MySQL实例一个group, 并为其设置合适的cpu.shares值
    2. 限制 blkio 使用,并打开 Innodb_flush_method=O_DIRECT
    3. 使用 device 子系统限制,如果占用空间过大,可以设置group对特定块设备不可写

    参考文献

    RedHat Cgroup Documents
    Blkio 子系统内核参数
    Mysql InnoDB IO configuration and flushing
    Linux资源管理-IO优先级
    A expanded CFQ scheduler for cgroups

  • 相关阅读:
    项目实战
    bootscript/javascript组件
    html5应用程序标签
    bootstrap框架应用
    bootstrap javascript插件部分的笔记整理
    bootstrap页面模板
    redis安装
    nginx + vsftpd 搭建 图片服务器
    centOs7 安装
    单链表的最装逼写法
  • 原文地址:https://www.cnblogs.com/Bozh/p/4810980.html
Copyright © 2020-2023  润新知