上篇文章我們簡要解析了用戶cpu時間相關概念及應用實踐,具體可參考鏈接?:
linux系統之User CPU time解析。
回顧之前的內容:在Linux操作系統中,通常采用8個不同的指標來研究Linux / unix操作系統中的CPU消耗:用戶CPU時間(us)、系統CPU時間(sy)、良好的CPU時間(ni)、空閑CPU時間(id)、等待CPU時間(wa)、硬件中斷CPU時間(hi),軟件中斷CPU時間(si),被盜CPU時間(st)。在本文中,我們主要針對“等待CPU時間”進行解析。

什么是“等待” CPU時間?
等待CPU時間表示CPU等待磁盤I / O或網絡I / O操作完成所花費的時間。等待時間過長表示由于該設備上的I / O操作,CPU被“絞死”了。為了獲得最佳性能,應該以使I / O等待CPU時間盡可能短為目標。如果等待時間> 10%,則需要對其進行問題排查。

我們可以通過以下場景來形象化描述I / O等待時間:大家應該經歷過或者已經在堵車中,有數百輛汽車在繁忙的道路上等待交通信號燈從“紅色”切換為“綠色”。但是由于技術上的故障(此刻,交警也不在現場),交通信號燈從“紅色”轉換為“綠色”經歷很長時間,遲遲沒有發生更替。結果呢?數百輛汽車就傻傻的在原地等待,等待第三方介入處理。如果沒有不及時處理,這將導致多種不良后果:乘客將無法及時到達目的地,駕駛員可能會感到沮喪并開始鳴喇叭(噪音污染),并且燃油將被浪費(空氣污染),更有甚者直接無視交規,釀成大禍。
如何查找“等待” CPU時間?
可從以下來源找到等待的CPU時間:
1、可以使用基于網絡的根本原因分析工具來報告“等待”的CPU時間。如果“等待” CPU時間超出閾值,該工具便能夠生成警報。


2、Linux/Unix命令行工具“ wa”字段中的“ top”中也能夠打印“等待” CPU時間,如下圖所示:
代碼語言:JavaScript代碼運行次數:0運行復制
[administrator@JavaLangOutOfMemory nacos-docker ]% toptop - 20:50:49 up 20:39, 2 users, load average: 1.13, 0.86, 1.05Tasks: 123 total, 1 running, 122 sleeping, 0 stopped, 0 zombie%Cpu(s): 9.1 us, 6.2 sy, 0.0 ni, 83.9 id, 0.0 wa, 0.0 hi, 0.8 si, 0.0 stKiB Mem : 3880584 total, 1006448 free, 859684 used, 2014452 buff/cacheKiB Swap: 0 total, 0 free, 0 used. 2583448 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2824 root 20 0 621140 357616 18272 S 10.9 9.2 118:20.09 kube-apiserver 2805 root 20 0 222392 49924 11240 S 7.6 1.3 81:42.59 kube-controller 11442 root 20 0 1512420 69476 33528 S 6.9 1.8 0:03.56 kubelet 2783 root 20 0 10.1g 58052 8152 S 5.3 1.5 48:55.54 etcd 1108 root 20 0 626628 85044 10092 S 4.3 2.2 45:54.18 dockerd 974 root 20 0 1078420 41340 4352 S 1.0 1.1 8:44.73 containerd 11794 root 20 0 162136 2248 1556 R 0.7 0.1 0:00.09 top 6 root 20 0 0 0 0 S 0.3 0.0 1:05.12 ksoftirqd/0 9 root 20 0 0 0 0 S 0.3 0.0 2:42.23 rcu_sched 395 root 20 0 0 0 0 S 0.3 0.0 2:26.41 xfsaild/dm-0 641 root 20 0 21540 1204 976 S 0.3 0.0 0:07.82 irqbalance 2858 root 20 0 147076 20348 6116 S 0.3 0.5 3:58.21 kube-scheduler 3884 root 20 0 142856 15952 4376 S 0.3 0.4 1:26.73 kube-proxy 11268 root 20 0 0 0 0 S 0.3 0.0 0:00.01 kworker/u4:0 1 root 20 0 125616 3692 2152 S 0.0 0.1 0:42.74 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H 7 root rt 0 0 0 0 S 0.0 0.0 0:03.03 migration/0 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 10 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 lru-add-drain 11 root rt 0 0 0 0 S 0.0 0.0 0:05.44 watchdog/0
如何模擬較高的“等待” CPU時間?
為了模擬高“等待” CPU報告,同樣原理,與之前的“用戶” CPU時間場景類似,我們寫個簡單的Demon。將其打成jar包,使其運行以模擬各種性能問題。當我們啟動此應用jar包時,它將導致主機上的“等待” CPU消耗激增。具體如下:
代碼語言:javascript代碼運行次數:0運行復制
[administrator@JavaLangOutOfMemory cpu ]% java -jar devopsDemo.jar PROBLEM_IOApplication started!Starting to write to iofile-01.logStarting to write to iofile-02.logStarting to write to iofile-03.logStarting to write to iofile-04.logStarting to write to iofile-05.logStarting to write to iofile-06.logRead & write 1000 times to iofile-05.logRead & write 1000 times to iofile-02.logRead & write 1000 times to iofile-01.logRead & write 1000 times to iofile-04.logRead & write 1000 times to iofile-03.logRead & write 1000 times to iofile-06.logRead & write 1000 times to iofile-04.logRead & write 1000 times to iofile-02.log... ...

針對此應用jar包,我們看下其部分代碼如下:
代碼語言:javascript代碼運行次數:0運行復制
public class IODemo { public void start() { for (int counter =1; counter <= 6; ++counter) { // Launch 6 threads. new IOThread ("iofile-" + counter + ".log").start(); } } }public class IOThread extends Thread { public String fileName; public static final String CONTENT = "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" + "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" + "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" + "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" + "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" + "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" + "Hello CPU World! We are building a world where cpu resources are wasted and memmory resource are leaking. n" public IOThread(String fileName) { this.fileName = fileName; } public void run() { int counter = 0; // Loop infinitely trying to read and close the file. while (true) { // Write the contents to the file. FileUtil.write(fileName, CONTENT); // Read the contents from the file. FileUtil.read(fileName); } } }

如何解決高“等待時間”?
如果我們的資源設備的I / O等待時間過長,則可以嘗試參考以下步驟進行優化及調整:
1、借助命令行及相關分析工具,該工具會指向應用程序中的代碼行,從而導致較高的I / O等待時間。

2、可以通過執行以下操作來優化應用程序的等待時間:
(1)減少數據庫調用次數
(2)優化數據庫查詢,以減少從數據庫返回到應用程序的數據
(3)減少對外部應用程序進行的網絡呼叫數量
(4)嘗試最小化在外部應用程序和您的應用程序之間發送的有效負載量
(5)嘗試減少寫入磁盤的文件數量。
(6)嘗試減少從磁盤讀取的數據量。
(7)確保僅將基本日志語句寫入磁盤。
3、確保我們的操作系統在安裝了所有補丁程序的最新版本上運行。從安全性的角度來看,這不僅很好,而且還可以提高性能。
4、確保在設備上分配了足夠的可用內存。缺少可用內存有兩個有害影響:
(1)如果缺少可用內存,則將交換進程進出內存。磁盤將頻繁寫入和讀取幾頁。它將增加磁盤I / O操作。
(2)如果可用內存較少,則操作系統將無法在內存中緩存常用磁盤塊。當高速緩存的磁盤塊被緩存時,I / O等待時間將減少。
5、將文件系統磁盤使用率保持在80%以下,以避免過多的碎片。當磁盤碎片過多時,I / O時間將增加。
6、如果上述所有步驟均失敗,則我們也可以嘗試考慮升級存儲以提高性能。例如,可以考慮切換到更快的SSD,NVMe,SAN存儲等。