今天在研究Docker進(jìn)程使用資源上限限制的時(shí)候看到了Cgroup,在Linux中其給用戶暴露出來的操作接口是文件系統(tǒng),我輸入mount -t cgroup
的時(shí)候顯示如下圖
可以看到有很多cpu、pid、內(nèi)存、設(shè)備等等的子目錄(子系統(tǒng)),拿
/sys/fs/cgroup/cpu
舉例,進(jìn)入該目錄,發(fā)現(xiàn)該文件夾下有以下文件:
cgroup.clone_children
cpu.cfs_period_us
cpu.rt_period_us
cpu.shares
notify_on_release
cgroup.procs
cpu.cfs_quota_us
cpu.rt_runtime_us
cpu.stat
tasks
其實(shí)當(dāng)你在該目錄下再創(chuàng)建一個(gè)文件夾的時(shí)候,文件夾內(nèi)部也是會(huì)默認(rèn)出現(xiàn)這些配置文件的。
那么其中的cfs是什么呢,沒錯(cuò)就是CFS,完全公平調(diào)度算法。
CFS思路很簡單,就是當(dāng)進(jìn)程得到調(diào)度以后,根據(jù)各個(gè)進(jìn)程的權(quán)重分配運(yùn)行時(shí)間,進(jìn)程每次調(diào)度分配的運(yùn)行時(shí)間的計(jì)算公式為:運(yùn)行時(shí)間 = 調(diào)度周期 * 進(jìn)程權(quán)重 / 所有進(jìn)程權(quán)重之和 (公式1)
。舉個(gè)例子,比如只有兩個(gè)進(jìn)程A, B,權(quán)重分別為1和2,調(diào)度周期設(shè)為30ms,那么分配給A的CPU時(shí)間為:30ms * (1/(1+2)) = 10ms;而B的CPU時(shí)間為:30ms * (2/(1+2)) = 20ms。那么在這30ms中A將運(yùn)行10ms,B將運(yùn)行20ms。 但是,vruntime并不是真實(shí)的運(yùn)行時(shí)間, 運(yùn)行時(shí)間和vruntime是怎么換算的呢?
vruntime = 實(shí)際運(yùn)行時(shí)間 * 1024 / 進(jìn)程權(quán)重 。 (公式2)
公式2中的1024,實(shí)際上它等于nice為0的進(jìn)程的權(quán)重,代碼中是NICE_0_LOAD。也就是說,所有進(jìn)程都以nice為0的進(jìn)程的權(quán)重1024作為基準(zhǔn),計(jì)算自己的vruntime增加速度。還以上面AB兩個(gè)進(jìn)程為例,B的權(quán)重是A的2倍,那么B的vruntime增加速度只有A的一半?,F(xiàn)在我們把公式2中的實(shí)際運(yùn)行時(shí)間用公式1來替換,最終我們可以得到
vruntime = 調(diào)度周期 * 1024 / 所有進(jìn)程總權(quán)重
(以上對于CFS內(nèi)容摘自https://blog.csdn.net/yetaibing1990/article/details/82716593 )
簡而言之就是誰的vruntime小就說明之前對于cpu占用時(shí)間短,所以相應(yīng)的下一個(gè)選擇這個(gè)進(jìn)程運(yùn)行的概率就高,而權(quán)重越大的vruntime增加的越慢,可以獲得更多的cpu執(zhí)行時(shí)間,這樣做到“完全公平”。
那講到這里,或許有讀者會(huì)問,nice是什么?其實(shí)上面引用的文章里有提到,但是對于其描述卻出錯(cuò)了,
nice值并不表示優(yōu)先級。
nice在這里可以通過與權(quán)重一一對應(yīng),nice值越大,權(quán)重越低。
nice的值的范圍為[-20,19],正值表示低優(yōu)先級,負(fù)值表示高優(yōu)先級,0表示不調(diào)整該進(jìn)程的優(yōu)先級。
nice值和優(yōu)先級(PRI)的關(guān)系如下公式:
PRI(new)=PRI(old)+nice
,所以,進(jìn)程nice值雖然會(huì)影響到優(yōu)先級的變化,但是卻不是進(jìn)程的優(yōu)先級。下圖就是進(jìn)程顯示的nice值。在Linux系統(tǒng)中可以使用top命令進(jìn)行查看。
那么我們?nèi)绾问褂胏group呢,其實(shí)主要是操作三個(gè)文件。首先是cpu.cfs_period_us,調(diào)度周期。里面默認(rèn)值應(yīng)該是100000.代表的是100000us,也就是100ms;其次是cpu.cfs_quota_us,表示在調(diào)度周期內(nèi)被分配到多少cpu時(shí)間。里面默認(rèn)值是-1,也就是無限制,在里面設(shè)置一個(gè)值就可以改成限制的時(shí)間,基礎(chǔ)單位也是us。例如我在cpu.cfs_quota_us中寫入20000,那么就是說我每100ms,其中只分配給這個(gè)進(jìn)程20ms的時(shí)間執(zhí)行,也就是對于cpu進(jìn)程的資源訪問進(jìn)行了限制。
而當(dāng)我們將進(jìn)程的PID寫入tasks文件內(nèi)的時(shí)候,設(shè)置就可以生效了。
Cgroups作為Linux容器技術(shù)的最基礎(chǔ)技術(shù)之一,Docker啟用容器的時(shí)候也能設(shè)置資源限制——輸入docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
可以設(shè)置好容器的cpu資源限制,相關(guān)限制文件可以在/sys/fs/cgroup/cpu/docker/xxxxxxx/cpu.cfs_period_us
和/sys/fs/cgroup/cpu/docker/xxxxxxx/cpu.cfs_quota_us
等文件中找到。(xxxxxxx是你的容器ID)。