干货 | 这次我们看看阿里的人是如何蹂躏CPU的
點(diǎn)擊上方“朱小廝的博客”,選擇“設(shè)為星標(biāo)”
回復(fù)”1024“獲取獨(dú)家整理的學(xué)習(xí)資料
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/chaos/how-alibaba-break-cpu/
?
配圖來源:天行九歌 · 焰靈姬
前言
?
在前面的系列文章中皮皮就介紹過如何使得CPU、I/O滿載,如何實(shí)現(xiàn)網(wǎng)絡(luò)延遲、丟包和中斷,如何模擬線程、進(jìn)程以及機(jī)器假死。如果對(duì)此不清楚的同學(xué)可以在文末的【相關(guān)系列】中查看相應(yīng)的文章。
本文介紹是阿里巴巴混沌工程工具ChaosBlade中的CPU滿載的故障模擬的實(shí)現(xiàn)方式。之前看的是Netflix的Simain Army中的實(shí)現(xiàn),看上去一目了然,通過java的形式調(diào)用一下模擬腳本,腳本的內(nèi)容如下:
#!/bin/bashcat?<<?EOF?>?/tmp/infiniteburn.sh #!/bin/bash while?true;do?openssl?speed; done EOFfor?i?in?{1..32} donohup?/bin/bash?/tmp/infiniteburn.sh?& done通過調(diào)用openssl speed來模擬CPU滿負(fù)荷運(yùn)作,這里的方式還比較粗暴,直接開了32個(gè)線程來執(zhí)行openssl speed這種CPU密集型計(jì)算程序。如果CPU的內(nèi)核數(shù)大于32,那么就需要修改這里的硬編碼腳本了。
通過翻看阿里巴巴混沌工程工具ChaosBlade的代碼(golang project),發(fā)現(xiàn)它對(duì)于CPU的蹂躪方式要細(xì)膩很多。比如CPU的內(nèi)核個(gè)數(shù)使用runtime.NumCPU()來獲取。當(dāng)然了還會(huì)有一些其它的附加細(xì)節(jié),這個(gè)下面會(huì)詳述。
我們先來簡(jiǎn)單的了解一下ChaosBlade對(duì)于這一塊的實(shí)現(xiàn)布局。在ChaosBlade中,我們實(shí)現(xiàn)故障(類似cpu 100%、I/O 100%、網(wǎng)絡(luò)中斷等)注入的入口是通過blade命令。例如:使得CPU滿載負(fù)荷,那么可以使用./blade create cpu fullload來實(shí)現(xiàn)。
其實(shí)ChaosBlade中的blade命令只是采用Cobra封裝的CLI入口,其內(nèi)部實(shí)現(xiàn)是調(diào)用bin/目錄下的chaos_burncpu程序。
ChaosBlades(releases版)的下載地址為:https://github.com/chaosblade-io/chaosblade/releases。解壓之后的目錄結(jié)構(gòu)為:
hidden@hidden:~/chaos/chaosblade-0.2.0$?tree . ├──?bin │???├──?chaos_burncpu │???├──?chaos_burnio │???├──?chaos_changedns │???├──?chaos_delaynetwork │???├──?chaos_dropnetwork │???├──?chaos_filldisk │???├──?chaos_killprocess │???├──?chaos_lossnetwork │???├──?chaos_stopprocess │???├──?cplus-chaosblade.spec.yaml │???├──?jvm.spec.yaml │???└──?tools.jar ├──?blade ├──?chaosblade.dat └──?lib?--<snip>可以看到bin/目錄下處理chaos_burncpu之外還有很多chaos_***形式的程序,比如chaos_burnio是讓I/O滿載負(fù)荷。這些chaos_***形式的程序的使用方式都是大同小異的。
使用指南
我們這里不使用ChaosBlade提供的blade命令,因?yàn)檫@只是外部的一層封裝,使用這個(gè)無法使我們能夠透徹的理解內(nèi)部的實(shí)現(xiàn)。我們這里使用bin/chaos_burncpu來演示一下具體的用法。調(diào)用方式如下:
bin/chaos_burncpu?--start這里命令可以讓當(dāng)前機(jī)器的CPU滿載負(fù)荷。取消CPU滿載負(fù)荷可以使用如下的命令:
bin/chaos_burncpu?--stopbin/chaos_burncpu命令還可以通過--cpu-count來指定CPU中需要滿載負(fù)荷的內(nèi)核個(gè)數(shù),示例如下:
#?指定需要滿載負(fù)荷的CPU的內(nèi)核個(gè)數(shù)為4 bin/chaos_burncpu?--start?--cpu-count?4假設(shè)現(xiàn)在測(cè)試所使用的機(jī)器的cpu共有4個(gè)內(nèi)核,那么我們讓其中3個(gè)內(nèi)核滿載,效果如何呢?首先運(yùn)行sar -u 1 100命令來監(jiān)測(cè)cpu的使用情況,然后運(yùn)行:
bin/chaos_burncpu?--start?--cpu-count?3可以在持續(xù)運(yùn)行sar命令的shell終端中看到CPU的%idle數(shù)值變成了25%左右:
02:21:35?PM?????CPU?????%user?????%nice???%system???%iowait????%steal?????%idle 02:21:44?PM?????all?????73.95??????0.00??????1.24??????0.00??????0.00?????24.81我們還可以指定讓某個(gè)CPU內(nèi)核滿載,比如下面的示例中讓內(nèi)核編號(hào)為1的滿載:
bin/chaos_burncpu?--start?--cpu-list?1sar命令中還可以通過—P參數(shù)查看指定編號(hào)的內(nèi)核的使用情況,比如使用sar -u -P 1 1 100來指定編號(hào)為1的CPU內(nèi)核的使用情況:
hidden@hidden:~$?sar?-u?-P?1?1?100 Linux?4.4.0-33.bm.1-amd64?(n224-008-172)?????08/15/2019??_x86_64_????(4?CPU)02:45:19?PM?????CPU?????%user?????%nice???%system???%iowait????%steal?????%idle 02:45:20?PM???????1?????98.00??????0.00??????2.00??????0.00??????0.00??????0.00 02:45:21?PM???????1?????98.99??????0.00??????1.01??????0.00??????0.00??????0.00可以看到這個(gè)內(nèi)核已經(jīng)滿載。至于怎么實(shí)現(xiàn)掛載單個(gè)CPU內(nèi)核的在下面會(huì)有詳細(xì)的介紹。
我們?cè)賮硗ㄟ^-P 0來看一下編號(hào)為0的CPU內(nèi)核的使用情況:
02:47:32?PM?????CPU?????%user?????%nice???%system???%iowait????%steal?????%idle 02:47:33?PM???????0??????1.00??????0.00??????2.00??????0.00??????0.00?????97.00 02:47:34?PM???????0??????0.00??????0.00??????0.00??????0.00??????0.00????100.00可以看到這個(gè)內(nèi)核還是處于空閑狀態(tài)(%idle接近100%)。
原理
CPU滿載
chaos_burncpu中實(shí)現(xiàn)CPU滿載負(fù)荷的邏輯其實(shí)相當(dāng)簡(jiǎn)單,通過程序讓CPU一直運(yùn)作即可。代碼如下:
func?burnCpu()?{runtime.GOMAXPROCS(cpuCount)for?i?:=?0;?i?<?cpuCount;?i++?{go?func()?{for?{for?i?:=?0;?i?<?2147483647;?i++?{}runtime.Gosched()?//讓出CPU時(shí)間片}}()}select?{}?//?wait?forever }讀者可以自己比較一下這個(gè)和Simain Army中的openssl speed的區(qū)別。
關(guān)閉
關(guān)閉CPU滿載負(fù)荷的過程也比較簡(jiǎn)單粗暴,總共分為兩步:
使用ps -ef | grep … 命令找出chaos_burncpu的pid。
使用kill -9 pid命令干掉它。
指定內(nèi)核滿載
我們?cè)谏厦婢土私獾酵ㄟ^--cpu-count可以指定CPU滿載的內(nèi)核個(gè)數(shù),通過--cpu-list可以指定內(nèi)核滿載。ChaosBlade相比于Simian Army中的細(xì)膩之處也就體現(xiàn)在這里。
--cpu-count的功能很好實(shí)現(xiàn),在上面的func burnCpu()函數(shù)中的cpuCount就是--cpu-count所指定的值。
--cpu-list的功能比較復(fù)雜,總共分為3步:
-
第一步:執(zhí)行nohup bin/chaos_burncpu --nohup --cpu-count 1 --cpu-processor [cpu內(nèi)核編號(hào)] > /dev/null 2>&1 &。假設(shè)我們要指定編號(hào)為1的內(nèi)核滿載,那么對(duì)應(yīng)的命令即為:nohup bin/chaos_burncpu --nohup --cpu-count 1 --cpu-processor 1 > /dev/null 2>&1 &。其實(shí)這個(gè)也只是個(gè)煙霧彈,實(shí)際上還是調(diào)用原本的bin/chaos_burncpu --start --cpu-count 1而已,只不過這里多指定了一個(gè)cpu-processor的信息。
-
第二步:執(zhí)行ps -ef | grep … 命令找出對(duì)應(yīng)的pid。
-
第三步:將進(jìn)程pid綁定到編號(hào)為cpu-processor的內(nèi)核上。那么這一步怎么操作呢?我們先來看一下CPU Affinity。
CPU Affinity
基本概念
CPU affinity (親和力/親和性)是一種調(diào)度屬性(scheduler property), 它可以將一個(gè)進(jìn)程"綁定" 到一個(gè)或一組CPU上。
將進(jìn)程與CPU綁定,最直觀的好處就是減少cpu之間的cache同步和切換,提高了cpu cache的命中率,提高代碼的效率。
從CPU架構(gòu)上,NUMA擁有獨(dú)立的本地內(nèi)存,節(jié)點(diǎn)之間可以通過互換模塊做連接和信息交互,因此每個(gè)CPU可以訪問整個(gè)系統(tǒng)的內(nèi)存,但是訪問遠(yuǎn)地內(nèi)存訪問效率大大降低,綁定CPU操作對(duì)此類系統(tǒng)運(yùn)行速度會(huì)有較大提升,UMA架構(gòu)下,多CPU通過系統(tǒng)總線訪問存儲(chǔ)模塊。不難看出,NUMA使用CPU綁定時(shí),每個(gè)核心可以更專注地處理一件事情,資源體系被充分使用,減少了同步的損耗。
表示方法
CPU affinity 使用位掩碼(bitmask)表示, 每一位都表示一個(gè)CPU, 置1表示"綁定"。最低位表示第一個(gè)邏輯CPU, 最高位表示最后一個(gè)邏輯CPU。CPU affinity典型的表示方法是使用16進(jìn)制,具體如下:
0x00000001is?processor?#00x00000003is?processors?#0?and?#10xFFFFFFFFis?all?processors?(#0?through?#31)taskset命令
taskset命名用于獲取或者設(shè)定CPU affinity。
#?命令行形式 Usage:?taskset?[options]?[mask?|?cpu-list]?[pid|cmd?[args...]]PARAMETERmask?:?cpu親和性,當(dāng)沒有-c選項(xiàng)時(shí),?其值前無論有沒有0x標(biāo)記都是16進(jìn)制的,當(dāng)有-c選項(xiàng)時(shí),其值是十進(jìn)制的.command?:?命令或者可執(zhí)行程序arg?:?command的參數(shù)pid?:?進(jìn)程ID,可以通過ps/top/pidof等命令獲取OPTIONS-a,?--all-tasks?(舊版本中沒有這個(gè)選項(xiàng))這個(gè)選項(xiàng)涉及到了linux中TID的概念,他會(huì)將一個(gè)進(jìn)程中所有的TID都執(zhí)行一次CPU親和性設(shè)置.TID就是Thread?ID,他和POSIX中pthread_t表示的線程ID完全不是同一個(gè)東西.Linux中的POSIX線程庫(kù)實(shí)現(xiàn)的線程其實(shí)也是一個(gè)進(jìn)程(LWP),這個(gè)TID就是這個(gè)線程的真實(shí)PID.-p,?--pid操作已存在的PID,而不是加載一個(gè)新的程序-c,?--cpu-list聲明CPU的親和力使用數(shù)字表示而不是用位掩碼表示.?例如?0,5,7,9-11.-h,?--helpdisplay?usage?information?and?exit-V,?--versionoutput?version?information?and?exitUSAGE1)?使用指定的CPU親和性運(yùn)行一個(gè)新程序taskset?[-c]?mask?command?[arg]...舉例:使用CPU0運(yùn)行l(wèi)s命令顯示/etc/init.d下的所有內(nèi)容?taskset?-c?0?ls?-al?/etc/init.d/2)?顯示已經(jīng)運(yùn)行的進(jìn)程的CPU親和性taskset?-p?pid舉例:查看init進(jìn)程(PID=1)的CPU親和性taskset?-p?13)?改變已經(jīng)運(yùn)行進(jìn)程的CPU親和力taskset?-p[c]?mask?pid舉例:打開2個(gè)終端,在第一個(gè)終端運(yùn)行top命令,第二個(gè)終端中首先運(yùn)行:[~]#?ps?-eo?pid,args,psr?|?grep?top?#獲取top命令的pid和其所運(yùn)行的CPU號(hào)其次運(yùn)行:[~]#?taskset?-cp?新的CPU號(hào)?pid???????#更改top命令運(yùn)行的CPU號(hào)最后運(yùn)行:[~]#?ps?-eo?pid,args,psr?|?grep?top?#查看是否更改成功PERMISSIONS一個(gè)用戶要設(shè)定一個(gè)進(jìn)程的CPU親和性,如果目標(biāo)進(jìn)程是該用戶的,則可以設(shè)置,如果是其他用戶的,則會(huì)設(shè)置失敗,提示?Operation?not?permitted.當(dāng)然root用戶沒有任何限制.任何用戶都可以獲取任意一個(gè)進(jìn)程的CPU親和性.應(yīng)用taskset
下面我們就來詳細(xì)實(shí)踐一下CPU指定內(nèi)核滿載的過程。
首先我們讓某個(gè)內(nèi)核滿載,這里我們還并未指定哪一個(gè)內(nèi)核(對(duì)應(yīng)前面所說第一步):
bin/chaos_burncpu?--start?--cpu-count?1第二步,我們找到這個(gè)進(jìn)程的pid:
hidden@hidden:~$?ps?-ef?|?grep?chaos_burncpu zhuzhon+??572792??490371?99?18:20?pts/0????00:00:14?bin/chaos_burncpu?--nohup?--cpu-count?1?--cpu-processor?1 zhuzhon+??572860??551590??0?18:20?pts/3????00:00:00?grep?chaos_burncpu此時(shí),我們查看pid=572792的進(jìn)程的親和力為f(即二進(jìn)制的1111,也就是CPU內(nèi)核編號(hào)0-3),也就是說CPU中的4個(gè)內(nèi)核都有可能運(yùn)行這個(gè)滿載程序。
hidden@hidden:~$?taskset?-p?572792 pid?572792's?current?affinity?mask:?fhidden@hidden:~$?taskset?-c?-p?572792 pid?572792's?current?affinity?list:?0-3上面第一步中,指定某個(gè)單獨(dú)的內(nèi)核滿載的實(shí)際效果應(yīng)該時(shí)每個(gè)內(nèi)核都會(huì)有一定的時(shí)間處于滿載狀態(tài)。對(duì)此有疑問的同學(xué)可以通過sar -u -P [cpu-processor] 1 1000來驗(yàn)證一下。
第三步,我們指定編號(hào)為0的內(nèi)核滿負(fù)荷:
hidden@hidden:~$?taskset?-cp?0?572792 pid?572792's?current?affinity?list:?0-3 pid?572792's?new?affinity?list:?0此時(shí)我們可以通過sar -u -P [cpu-processor] 1 1000命令來檢測(cè)4個(gè)內(nèi)核的各個(gè)使用情況。不出意外的話,內(nèi)核編號(hào)為0的檢測(cè)結(jié)果應(yīng)該和下面的類似:
hidden@hidden:~$?sar?-u?-P?0?1?1000 Linux?4.4.0-33.bm.1-amd64?(n224-008-172)?????08/15/2019??_x86_64_????(4?CPU)06:22:08?PM?????CPU?????%user?????%nice???%system???%iowait????%steal?????%idle 06:38:46?PM???????0????100.00??????0.00??????0.00??????0.00??????0.00??????0.00 06:38:47?PM???????0????100.00??????0.00??????0.00??????0.00??????0.00??????0.00 06:38:48?PM???????0????100.00??????0.00??????0.00??????0.00??????0.00??????0.00而其他內(nèi)核的%idle應(yīng)該都接近在100%。
總結(jié)
本文不僅介紹了如何“蹂躪”CPU,還附帶了一個(gè)知識(shí)點(diǎn)就是CPU affinity,程序開發(fā)者比機(jī)器更懂程序,如果用好它,可以有意想不到的效果。還有,在之前的《看我如何作死 | 將CPU、IO打爆》中不僅介紹了如何使得CPU滿載,還介紹了I/O如何滿載,這里不妨透漏一下,阿里和Netflix對(duì)于I/O滿載的模擬都是使用的linux dd工具,所以本文就不多做贅述啦。
?
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/chaos/how-alibaba-break-cpu/
想知道更多?掃描下面的二維碼關(guān)注我
相關(guān)推薦:
-
《科普 | 明星公司之Netflix》
-
《看我如何作死 | 將CPU、IO打爆》
-
《看我如何作死 | 網(wǎng)絡(luò)延遲、丟包、中斷一個(gè)都沒落下》
-
《看我如何假死!》
?
?
友情推廣:極客時(shí)間課程《編譯原理之美》,掃碼購(gòu)買后可以添加皮皮微信:>>Learn More<<可獲得返現(xiàn)(返現(xiàn)24元,購(gòu)買時(shí)輸入優(yōu)惠碼:666bianyi還可以再減5元),記得留下你的極客昵稱。
?
點(diǎn)個(gè)"在看"唄^_^
總結(jié)
以上是生活随笔為你收集整理的干货 | 这次我们看看阿里的人是如何蹂躏CPU的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科普 | 5G基站功耗,到底有多可怕?
- 下一篇: 科普 | CPU 是如何工作的?