怎麼調整CPU資源分配,如何將資源公平地分配給各個進程

怎麼調整CPU資源分配,如何將資源公平地分配給各個進程
但是,如果你需要給一個重要進程提高優先級時,該怎麼做呢? 或者是,如何降低一個進程的優先級? 又或者,如何限制一組進程所使用的資源呢?
答案是需要由用戶來爲內核指定進程的優先級
大部分進程啓動時的優先級是相同的,因此Linux內核會公平地進行調度。 如果想讓一個CPU密集型的進程運行在較低優先級,那麼你就得事先配置好調度器。

下面介紹3種控制進程運行時間的方法:

使用 nice 命令手動降低任務的優先級。
使用 cpulimit 命令不斷的暫停進程,以控制進程所佔用處理能力不超過特定限制。
使用linux內建的control groups(控制組)功能,它提供了限制進程資源消耗的機制。
我們來看一下這3個工具的工作原理和各自的優缺點。

模擬高cpu佔用率

在分析這3種技術前,我們要先安裝一個工具來模擬高CPU佔用率的場景。我們會用到CentOS作爲測試系統,並使用Mathomatic toolkit中的質數生成器來模擬CPU負載。

很不幸,在CentOS上這個工具沒有預編譯好的版本,所以必須要從源碼進行安裝。先從 http://mathomatic.orgserve.de/mathomatic-16.0.5.tar.bz2 這個鏈接下載源碼包並解壓。然後進入 mathomatic-16.0.5/primes 文件夾,運行 make 和 sudo make install 進行編譯和安裝。這樣,就把 matho-primes 程序安裝到了 /usr/local/bin 目錄中。

接下來,通過命令行運行:

/usr/local/bin/matho-primes 09999999999>/dev/null&
程序運行後,將輸出從0到9999999999之間的質數。因爲我們並不需要這些輸出結果,直接將輸出重定向到/dev/null就好。

現在,使用top命令就可以看到matho-primes進程榨乾了你所有的cpu資源。

好了,接下來(按q鍵)退出 top 並殺掉 matho-primes 進程(使用 fg 命令將進程切換到前臺,再按 CTRL+C)

nice命令

下來介紹一下nice命令的使用方法,nice命令可以修改進程的優先級,這樣就可以讓進程運行得不那麼頻繁。 這個功能在運行cpu密集型的後臺進程或批處理作業時尤爲有用。 nice值的取值範圍是[-20,19],-20表示最高優先級,而19表示最低優先級。 Linux進程的默認nice值爲0。使用nice命令(不帶任何參數時)可以將進程的nice值設置爲10。這樣調度器就會將此進程視爲較低優先級的進程,從而減少cpu資源的分配。

下面來看一個例子,我們同時運行兩個 matho-primes 進程,一個使用nice命令來啓動運行,而另一個正常啓動運行:

nice matho-primes 0 9999999999 >/dev/null&
matho-primes 0 9999999999 >/dev/null&
再運行top命令。

看到沒,正常運行的進程(nice值爲0)獲得了更多的cpu運行時間,相反的,用nice命令運行的進程佔用的cpu時間會較少(nice值爲10)。

在實際使用中,如果你要運行一個CPU密集型的程序,那麼最好用nice命令來啓動它,這樣就可以保證其他進程獲得更高的優先級。 也就是說,即使你的服務器或者臺式機在重載的情況下,也可以快速響應。

nice 還有一個關聯命令叫做 renice,它可以在運行時調整進程的 nice 值。使用 renice 命令時,要先找出進程的 PID。下面是一個例子:

renice +101234
其中,1234是進程的 PID。

測試完 nice 和 renice 命令後,記得要將 matho-primes 進程全部殺掉。

cpulimit命令

接下來介紹 cpulimit 命令的用法。 cpulimit 命令的工作原理是爲進程預設一個 cpu 佔用率門限,並實時監控進程是否超出此門限,若超出則讓該進程暫停運行一段時間。cpulimit 使用 SIGSTOP 和 SIGCONT 這兩個信號來控制進程。它不會修改進程的 nice 值,而是通過監控進程的 cpu 佔用率來做出動態調整。

cpulimit 的優勢是可以控制進程的cpu使用率的上限值。但與 nice 相比也有缺點,那就是即使 cpu 是空閒的,進程也不能完全使用整個 cpu 資源。

在 CentOS 上,可以用下面的方法來安裝它:

wget -O cpulimit.zip https://github.com/opsengine/cpulimit/archive/master.zip
unzip cpulimit.zip
cd cpulimit-master
make
sudo cp src/cpulimit /usr/bin
上面的命令行,會先從從 GitHub 上將源碼下載到本地,然後再解壓、編譯、並安裝到 /usr/bin 目錄下。

cpulimit 的使用方式和 nice 命令類似,但是需要用戶使用 -l 選項顯式地定義進程的 cpu 使用率上限值。舉例說明:

cpulimit -l 50 matho-primes 09999999999>/dev/null&

從上面的例子可以看出 matho-primes 只使用了50%的 cpu 資源,剩餘的 cpu 時間都在 idle。

cpulimit 還可以在運行時對進程進行動態限制,使用 -p 選項來指定進程的 PID,下面是一個實例:

cpulimit -l 50-p 1234
其中,1234是進程的 PID。

以下文檔見:https://www.cnblogs.com/yanghuahui/p/3751826.html 即可:

本文用腳本運行示例進程,來驗證Cgroups關於cpu、內存、io這三部分的隔離效果。

測試機器:CentOS release 6.4 (Final)

啓動Cgroups

service cgconfig start #開啓cgroups服務
chkconfig cgconfig on #開啓啓動
在/cgroup,有如下文件夾,默認是多掛載點的形式,即各個子系統的配置在不同的子文件夾下

[root@localhost /]# ls /cgroup/
blkio cpu cpuacct cpuset devices freezer memory net_cls

cgroups管理進程cpu資源
跑一個耗cpu的腳本

x=0
while [ True ];do
x=$x+1
done;
top可以看到這個腳本基本佔了100%的cpu資源

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
30142 root 20 0 104m 2520 1024 R 99.7 0.1 14:38.97 sh
下面用cgroups控制這個進程的cpu資源

mkdir -p /cgroup/cpu/foo/ #新建一個控制組foo
echo 50000 > /cgroup/cpu/foo/cpu.cfs_quota_us #將cpu.cfs_quota_us設爲50000,相對於cpu.cfs_period_us的100000是50%
echo 30142 > /cgroup/cpu/foo/tasks
然後top的實時統計數據如下,cpu佔用率將近50%,看來cgroups關於cpu的控制起了效果

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 30142 root 20 0 105m 2884 1024 R 49.4 0.2 23:32.53 sh
cpu控制組foo下面還有其他的控制,還可以做更多其他的關於cpu的控制

[root@localhost ~]# ls /cgroup/cpu/foo/
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 tasks

cgroups管理進程內存資源
跑一個耗內存的腳本,內存不斷增長

x="a"
while [ True ];do
x=$x$x
done;
top看內存佔用穩步上升

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 30215 root 20 0 871m 501m 1036 R 99.8 26.7 0:38.69 sh
30215 root 20 0 1639m 721m 1036 R 98.7 38.4 1:03.99 sh
30215 root 20 0 1639m 929m 1036 R 98.6 49.5 1:13.73 sh
下面用cgroups控制這個進程的內存資源

mkdir -p /cgroup/memory/foo
echo 1048576 > /cgroup/memory/foo/memory.limit_in_bytes #分配1MB的內存給這個控制組
echo 30215 > /cgroup/memory/foo/tasks
發現之前的腳本被kill掉

[root@localhost ~]# sh /home/test.sh
已殺死
因爲這是強硬的限制內存,當進程試圖佔用的內存超過了cgroups的限制,會觸發out of memory,導致進程被kill掉。

實際情況中對進程的內存使用會有一個預估,然後會給這個進程的限制超配50%比如,除非發生內存泄露等異常情況,纔會因爲cgroups的限制被kill掉。

也可以通過配置關掉cgroups oom kill進程,通過memory.oom_control來實現(oom_kill_disable 1),但是儘管進程不會被直接殺死,但進程也進入了休眠狀態,無法繼續執行,仍讓無法服務。

關於內存的控制,還有以下配置文件,關於虛擬內存的控制,以及權值比重式的內存控制等

複製代碼
[root@localhost /]# ls /cgroup/memory/foo/
cgroup.event_control memory.force_empty memory.memsw.failcnt
memory.memsw.usage_in_bytes memory.soft_limit_in_bytes memory.usage_in_bytes tasks
cgroup.procs memory.limit_in_bytes memory.memsw.limit_in_bytes
memory.move_charge_at_immigrate memory.stat memory.use_hierarchy
memory.failcnt memory.max_usage_in_bytes memory.memsw.max_usage_in_bytes
memory.oom_control memory.swappiness notify_on_release
複製代碼

cgroups管理進程io資源
跑一個耗io的腳本

dd if=/dev/sda of=/dev/null &
通過iotop看io佔用情況,磁盤速度到了284M/s

30252 be/4 root 284.71 M/s 0.00 B/s 0.00 % 0.00 % dd if=/dev/sda of=/dev/null
下面用cgroups控制這個進程的io資源

mkdir -p /cgroup/blkio/foo

echo '8:0 1048576' > /cgroup/blkio/foo/blkio.throttle.read_bps_device
#8:0對應主設備號和副設備號,可以通過ls -l /dev/sda查看
echo 30252 > /cgroup/blkio/foo/tasks
再通過iotop看,確實將讀速度降到了1M/s

30252 be/4 root 993.36 K/s 0.00 B/s 0.00 % 0.00 % dd if=/dev/sda of=/dev/null
對於io還有很多其他可以控制層面和方式,如下

複製代碼
[root@localhost ~]# ls /cgroup/blkio/foo/
blkio.io_merged blkio.io_serviced blkio.reset_stats
blkio.throttle.io_serviced blkio.throttle.write_bps_device blkio.weight cgroup.procs
blkio.io_queued blkio.io_service_time blkio.sectors
blkio.throttle.read_bps_device blkio.throttle.write_iops_device blkio.weight_device notify_on_release
blkio.io_service_bytes blkio.io_wait_time blkio.throttle.io_service_bytes
blkio.throttle.read_iops_device blkio.time cgroup.event_control tasks
複製代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章