CentOS:作業系統級監控及常用計數器解析---除CPU以外

絲瓜呆呆發表於2021-06-13

I/O

I/O 其實是挺複雜的一個邏輯,但我們今天只說在做效能分析的時候,應該如何定位問題。

對效能優化比較有經驗的人(或者說見過世面比較多的人)都會知道,當一個系統調到非常精緻的程度時,基本上會卡在兩個環節上,對計算密集型的應用來說,會卡在 CPU 上;對 I/O 密集型的應用來說,瓶頸會卡在 I/O 上。

我們對 I/O 的判斷邏輯關係是什麼呢?

我們先畫一個 I/O 基本的邏輯過程。我們很多人嘴上說 I/O,其實腦子裡想的都是 Disk I/O,但實際上一個資料要想寫到磁碟當中,沒那麼容易,步驟並不簡單。

 I/O 有很多原理細節,那我們如何能快速地做出相應的判斷呢?首先要祭出的一個工具就是iostat。

 

 

 在這張圖中,我們取出一條資料來做詳細看下:


Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz
vda 0.00 0.67 18.33 114.33 540.00 54073.33 823.32
avgqu-sz await r_await w_await svctm %util
127.01 776.75 1.76 901.01 7.54 100.00

我解釋一下其中幾個關鍵計數器的含義。

svctm代表 I/O 平均響應時間。請注意,這個計數器,有很多人還把它當個寶一樣,實際上在 man 手冊中已經明確說了:“Warning! Do not trust this field any more. This field will be removed in a future sysstat version.” 也就是說,這個資料你愛看就愛,不一定準。

w_await表示寫入的平均響應時間;r_await表示讀取的平均響應時間;r/s表示每秒讀取次數;w/s表示每秒寫入次數。

而 IO/s 的關鍵計算是這樣的:


IO/s = r/s + w/s = 18.33+114.33 = 132.66
%util = ( (IO/s * svctm) /1000) * 100% = 100.02564%

這個%util是用svctm算來的,既然svctm都不一定準了,那這個值也只能參考了。還好我們還有其他工具可以接著往深了去定位,那就是iotop。


Total DISK READ : 2.27 M/s | Total DISK WRITE : 574.86 M/s
Actual DISK READ: 3.86 M/s | Actual DISK WRITE: 34.13 M/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
394 be/3 root 0.00 B/s 441.15 M/s 0.00 % 85.47 % [jbd2/vda1-8]
32616 be/4 root 1984.69 K/s 3.40 K/s 0.00 % 42.89 % kube-controllers
13787 be/4 root 0.00 B/s 0.00 B/s 0.00 % 35.41 % [kworker/u4:1]
...............................

從上面的Total DISK WRITE/READ就可以知道當前的讀寫到底有多少了,預設是按照I/O列來排序的,這裡有Total,也有Actual,並且這兩個並不相等,為什麼呢?

因為 Total 的值顯示的是使用者態程式與核心態程式之間的速度,而 Actual 顯示的是核心塊裝置子系統與硬體之間的速度。

而在I/O互動中,由於存在cache和在核心中會做I/O排序,因此這兩個值並不會相同。那如果你要說磁碟的讀寫能力怎麼樣,我們應該看的是Actual。這個沒啥好說的,因為Total再大,不能真實寫到硬碟上也是沒用的。在下面的執行緒列表中,通過排序,就可以知道是哪個執行緒(注意在第一列是 TID 哦)佔的I/O高了。

Memory

關於記憶體,要說作業系統的記憶體管理,那大概開一個新專欄也不為過。但是在效能測試的專案中,如果不做底層的測試,基本上在上層語言開發的系統中,比如說 Java、Go、C++ 等,在分析過程中都直接看業務系統就好了。在作業系統中,分析業務應用的時候,我們會關注的記憶體內容如下面的命令所示:

[root@7dgroup ~]# free -m             
        total        used        free      shared  buff/cache   available
Mem:           3791        1873         421         174        1495        1512
Swap:             0           0           0
[root@7dgroup ~]#

total肯定是要優先看的,其次是available,這個值才是系統真正可用的記憶體,而不是free。

因為 Linux 通常都會把用的記憶體給cache,但是不一定會用,所以free肯定會越來越少,但是available是計算了buff和cache中不用的記憶體的,所以只要available多,就表示記憶體夠用。

當出現記憶體洩露或因其他原因導致實體記憶體不夠用的時候,作業系統就會呼叫OOM Killer,這個程式會強制殺死消耗記憶體大的應用。這個過程是不商量的,然後你在“dmesg”中就會看到如下資訊。

[12766211.187745] Out of memory: Kill process 32188 (java) score 177 or sacrifice child
[12766211.190964] Killed process 32188 (java) total-vm:5861784kB, anon-rss:1416044kB, file-rss:0kB, shmem-rss:0kB

 這種情況只要出現,TPS 肯定會掉下來,如果你有負載均衡的話,壓力工具中的事務還是可能有成功的。

但如果你只有一個應用節點,或者所有應用節點都被OOM Killer給幹掉了,那 TPS 就會是這樣的結果。

 

 

對記憶體監控,可以看到這樣的趨勢:

 

 記憶體慢慢被耗光,但是殺掉應用程式之後,free記憶體立即就有了。你看上面這個圖,就是一個機器上有兩個節點,先被殺了一個,另一個接著洩露,又把記憶體耗光了,於是又被殺掉,最後記憶體全都空閒了。

這樣的例子還挺常見。當然對這種情況的分析定位,只看實體記憶體已經沒有意義了,更重要的是看應用的記憶體是如何被消耗光的。

對於記憶體的分析,你還可以用nmon和cat/proc/meminfo看到更多資訊。如果你的應用是需要大頁處理的,特別是大資料類的應用,需要關注下HugePages相關的計數器。

記憶體我們就說到這裡,總之,要關注available記憶體的值。

NetWork

這裡我們就來到了網路分析的部分了,在說握手之前,我們先看網路的分析決策鏈。

 

 

請看上圖中,在判斷了瓶頸在網路上之後,如果知道某個程式的網路流量大,首先肯定是要考慮減少流量,當然要在保證業務正常執行,TPS 也不降低的情況下。

Recv_Q 和 Send_Q

當然我們還要幹一件事,就是可能你並不知道是在哪個具體的環節上出了問題,那就要學會判斷了。網路I/O棧也並不簡單,看下圖:

 

 

資料傳送過程是這樣的:

應用把資料給到tcp_wmem就結束它的工作了,由核心接過來之後,經過傳輸層,再經過佇列、環形緩衝區,最後通過網路卡發出去。

資料接收過程則是這樣的:

網路卡把資料接過來,經過佇列、環形緩衝區,再經過傳輸層,最後通過tcp_rmem給到應用。你似乎懂了對不對?那麼在這個過程中,我們有什麼需要關注的呢?首先肯定是看佇列,通過netstat或其他命令可以看到Recv_Q和Send_Q,這兩項至少可以告訴你瓶頸會在哪一端。如下圖所示:

 

 

我畫個表清晰地判斷一下瓶頸點。

 

相關文章