这里的权重其实是 shares 。我把它叫做权重是因为这个值可以理解为对资源占用的权重。这种资源隔离方式事实上也是对 cpu 时间的进行分配。区别是作用在 cfs 调度器的权重值上。从用户的角度看,无非就是给每个 cgroup 配置一个 share 值, cpu 在进行时间分配的时候,按照 share 的大小比率来确定 cpu 时间的百分比。它对比 cpuquota 的优势是,当进程不在 cfs 可执行调度队列中的时候,这个权重是不起作用的。就是说,一旦其他 cgroup 的进程释放 cpu 的时候,正在占用 cpu 的进程可以全占所有计算资源。而当有多个 cgroup 进程都要占用 cpu 的时候,大家按比例分配。
我们照例通过实验来说明这个情况,配置方法也很简单,修改 cgconfig.conf ,添加字段,并重启服务:
group zorro {
cpu {
cpu.shares = 1000;
}
}
[root@zorrozou-pc ~]# service cgconfig restart
配置完之后,我们就给 zorro 组配置了一个 shares 值为 1000 ,但是实际上如果系统中只有这一个组的话, cpu 看起来对他是没有限制的。现在的执行效果是这样:
[root@zorrozou-pc ~]# mpstat -P ALL 1
17:17:29 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
17:17:30 all 99.88 0.00 0.12 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 2 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 3 99.01 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 4 99.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 5 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 6 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 7 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 8 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 9 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 10 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 11 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 12 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 13 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 14 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 15 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 16 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 17 99.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 18 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 19 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 20 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 21 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 22 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
17:17:30 23 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
[zorro@zorrozou-pc ~/test]$ time ./prime_thread_zorro &> /dev/null
real 0m8.937s
user 3m32.190s
sys 0m0.225s
如显示, cpu 我们是独占的。那么什么时候有隔离效果呢?是系统中有别的 cgroup 也要占用 cpu 的时候,就能看出效果了。比如此时我们再添加一个 jerry , shares 值也配置为 1000 ,并且让 jerry 组一直有占用 cpu 的进程在运行。
group jerry {
cpu {
cpu.shares = "1000";
}
}
top - 17:24:26 up 1 day, 5 min, 2 users, load average: 41.34, 16.17, 8.17
Tasks: 350 total, 2 running, 348 sleeping, 0 stopped, 0 zombie
Cpu0 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu4 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu5 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu6 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu7 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu8 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu9 : 99.7%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.3%hi, 0.0%si, 0.0%st
Cpu10 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu11 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu12 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu13 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu14 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu15 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu16 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu17 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu18 : 99.3%us, 0.7%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu19 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu20 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu21 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu22 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu23 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 131904480k total, 4938020k used, 126966460k free, 136140k buffers
Swap: 2088956k total, 0k used, 2088956k free, 3700480k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13945 jerry 20 0 390m 872 392 S 2397.2 0.0 48:42.54 jerry
我们以 jerry 用户身份执行了一个进程一直 100%占用 cpu ,从上面的显示可以看到,这个进程占用了 2400%的 cpu ,是因为每个 cpu 核心算 100%, 24 个核心就是 2400%。此时我们再以 zorro 身份执行筛质数的程序,并察看这个程序占用 cpu 的百分比:
top - 19:44:11 up 1 day, 2:25, 3 users, load average: 60.91, 50.92, 48.85
Tasks: 336 total, 3 running, 333 sleeping, 0 stopped, 0 zombie
Cpu0 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu4 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu5 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu6 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu7 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu8 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu9 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu10 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu11 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu12 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu13 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu14 : 99.7%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.3%hi, 0.0%si, 0.0%st
Cpu15 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu16 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu17 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu18 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu19 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu20 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu21 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu22 : 99.7%us, 0.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu23 :100.0%us, 0.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 131904480k total, 1471772k used, 130432708k free, 144216k buffers
Swap: 2088956k total, 0k used, 2088956k free, 322404k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
13945 jerry 20 0 390m 872 392 S 1200.3 0.0 3383:04 jerry
9311 zorro 20 0 390m 872 392 R 1197.0 0.0 0:51.56 prime_thread_zo
通过 top 我们可以看到,以 zorro 用户身份执行的进程和 jerry 进程平分了 cpu ,每人 50%。 zorro 筛质数执行的时间为:
[zorro@zorrozou-pc ~/test]$ time ./prime_thread_zorro &> /dev/null
real 0m15.152s
user 2m58.637s
sys 0m0.220s
[zorro@zorrozou-pc ~/test]$ time ./prime_thread_zorro &> /dev/null
real 0m15.465s
user 3m0.706s
sys 0m0.221s
根据这个时间看起来,基本与通过 cpuquota 方式分配 50%的 cpu 时间以及通过 cpuset 方式分配 12 个核心的情况相当,而且效率还稍微高一些。当然我要说明的是,这里几乎两秒左右的效率的提高并不具备很大的参考性,它与 jerry 进程执行的运算是有很大相关性的。此时 jerry 进程执行的是一个多线程的 while 死循环,占满所有 cpu 跑。当我们把 jerry 进程执行的内容同样变成筛质数的时候, zorro 用户的进程执行效率的参考值就比较标准了:
[zorro@zorrozou-pc ~/test]$ time ./prime_thread_zorro &> /dev/null
real 0m17.521s
user 3m32.684s
sys 0m0.254s
[zorro@zorrozou-pc ~/test]$ time ./prime_thread_zorro &> /dev/null
real 0m17.597s
user 3m32.682s
sys 0m0.253s
如程序执行显示,执行效率基本与 cpuset 和 cpuquota 相当。
这又引发了另一个问题请大家思考:为什么 jerry 用户执行的运算的逻辑不同会影响 zorro 用户的运算效率?
我们可以将刚才 cpuset 和 cpuquota 的对比列表加入 cpushare 一列来一起对比了,为了方便参考,我们都以 cpuset 为基准进行比较:
shares zorro/shares jerry (核心数) | cpuset realtime | cpushare realtime | cpuquota realtime |
---|---|---|---|
2000/22000(2) | 1m46.557s | 1m41.691s | 1m36.786s |
4000/20000(4) | 0m53.271s | 0m51.801s | 0m51.067s |
6000/18000(6) | 0m35.528s | 0m35.152s | 0m34.539s |
8000/16000(8) | 0m26.643s | 0m26.372s | 0m25.923s |
12000/12000(12) | 0m17.839s | 0m17.694s | 0m17.347s |
16000/8000(16) | 0m13.384s | 0m13.388s | 0m13.015s |
24000/0(24) | 0m8.972s | 0m8.943s | 0m8.932s |
请注意一个问题,由于 cpushares 无法像 cpuquota 或者 cpuset 那样只执行 zorro 用户的进程,所以在进行 cpushares 测试的时候,必须让 jerry 用户同时执行相同的筛质数程序,才能使两个用户分别分到相应比例的 cpu 时间。这样可能造成本轮测试结果的不准确。通过对比看到,当比率分别都配置了相当于两个核心的计算能力的情况下,本轮测试是 cpuquota 方式消耗了 1m36.786s 稍快一些。为了保证相对公平的环境作为参照,我们将重新对这轮测试进行数据采集,这次在 cpuset 和 cpuquota 的压测时,都用 jerry 用户执行一个干扰程序作为参照,重新分析数据。当然, cpushares 的测试数据就不必重新测试了:
shares zorro/shares jerry (核心数) | cpuset realtime | cpushare realtime | cpuquota realtime |
---|---|---|---|
2000/22000(2) | 1m46.758s | 1m41.691s | 1m42.341s |
4000/20000(4) | 0m53.340s | 0m51.801s | 0m51.512s |
6000/18000(6) | 0m35.525s | 0m35.152s | 0m34.392s |
8000/16000(8) | 0m26.738s | 0m26.372s | 0m25.772s |
12000/12000(12) | 0m17.793s | 0m17.694s | 0m17.256s |
16000/8000(16) | 0m13.366s | 0m13.388s | 0m13.155s |
24000/0(24) | 0m8.930s | 0m8.943s | 0m8.939s |
至此, cgroup 中针对 cpu 的三种资源隔离都介绍完了,分析我们的测试数据可以得出一些结论:
大家可以根据这三种不同隔离手段特点,针对自己的环境来选择不同的方式进行 cpu 资源的隔离。当然,这些手段也可以混合使用,以达到更好的 QOS 效果。
但是可是 but ,这就完了么?
显然并没有。。。。。。
以上测试只针对了一种计算场景,这种场景在如此的简单的情况下,影响测试结果的条件已经很复杂了。如果是其他情况呢?我们线上真正跑业务的环境会这么单纯么?显然不会。我们不可能针对所有场景得出结论,想要找到适用于自己场景的隔离方式,还是需要在自己的环境中进行充分测试。在此只能介绍方法,以及针对一个场景的参考数据,仅此而已。单就这一个测试来说,它仍然不够全面,无法体现出内核 cpu 资源隔离的真正面目。众所周知, cpu 使用主要分两个部分, user 和 sys 。上面这个测试,由于测试用例的选择,只关注了 user 的使用。那么如果我们的 sys 占用较多会变成什么样呢?
1
virusdefender 2015-12-29 00:42:23 +08:00
三篇大致的看完了,很棒~~
|
2
Aydon0 2015-12-31 20:35:25 +08:00 via Android
写的非常好,赞!
|