我相信有一些人看到這篇文章的標題肯定有種不想看的感覺,因為這樣的內容實在被寫得太多太多了。作業系統分析嘛,無非就是 CPU 使用率、I/O 使用率、記憶體使用率、網路使用率等各種使用率的描述。
然而因為視角的不同,在效能測試和分析中,這始終是我們繞不過去的分析點。我們得知道什麼時候才需要去分析作業系統,以及要分析作業系統的什麼內容。
首先,我們前面在效能分析方法中提到,效能分析要有起點,通常情況下,這個起點就是響應時間、TPS 等壓力工具給出來的資訊。
我們判斷了有瓶頸之後,通過拆分響應時間就可以知道在哪個環節上出了問題,再去詳細分析這個作業系統。這就需要用到我們的分析決策樹了。
在分段分層確定了這個系統所執行的應用有問題之後,還要記起另一件事情,就是前面提到的“全域性—定向”的監控思路。
既然說到了全域性,我們得先知道作業系統中,都有哪些大的模組。這裡就到了幾乎所有效能測試人員看到就想吐的模組了,CPU、I/O、Memory、Network…
沒辦法,誰讓作業系統就這麼點東西呢。我先畫一個思維導圖給你看一下。
我很努力地把一些常見指標的相應關係都畫到了圖中,你是不是已經看暈了?看暈就對了,彆著急。我們先要知道的是,面對這些大的模組,到底要用什麼的監控手段來實現對它們的監控呢?
要知道,在一篇文章中不可能詳盡地描述作業系統,我會盡量把我工作中經常使用到的一些和效能分析相關的、使用頻度高的知識點整理給你。
監控命令
我們經常用到的 Linux 監控命令大概有這些:top、atop、vmstat、iostat、iotop、dstat、sar等……
請你注意我這裡列的監控命令是指可以監控到相應模組的計數器,而不是說只能監控這個模組,因為大部分命令都是綜合的工具集。
像這樣的監控工具還能列上一堆,但這並不是關鍵,關鍵的是我們在什麼時候能想起來用這些工具,以及知道這些工具的侷限性。
比如說 top,它能看 CPU、記憶體、Swap、執行緒列表等資訊,也可以把 I/O 算進去,因為它有 CPU 的 wa 計數器,但是它看不了 Disk 和 Network,這就是明顯的侷限性。之後出現的atop對很多內容做了整理,有了 Disk 和 Net 資訊,但是呢,在一些 Linux 發行版中又不是預設安裝的。vmstat呢?它能看 CPU、記憶體、佇列、Disk、System、Swap 等資訊,但是它又看不了執行緒列表和網路資訊。
像這樣的侷限,我還能說上兩千字。當工具讓你眼花繚亂的時候,不要忘記最初的目標,我們要監控的是這幾大模組:CPU、I/O、Memory、Network、System、Swap。
然後,我們再來對應前面提到的“全域性—定向”監控的思路。如果你現在僅用命令來監控這個系統,你要執行哪幾個呢?
對應文章前面的思維導圖,我們做一個細緻的表格。
你會發現,vmstat可以看 Swap,但它能看的是si和so,看不到其他的計數器,但是top可以看到這些計數器……像這樣的細節還有很多。
因為計數器非常多,又不是每個都常用。但是萬一某個時候就需要用了呢?這個時候如果你不知道的話,就無法繼續分析下去。
這裡我主要想告訴你什麼呢?就是用命令的時候,你要知道這個命令能幹什麼,不能幹什麼。你可能會說,有這些麼多的計數器,還有這麼多的命令,光學個 OS 我得學到啥時候去?
我要告訴你的是監控的思考邏輯。你要知道的是,正是因為你要監控 CPU 的某個計數器才執行了這個命令,而不是因為自己知道這個命令才去執行。這個關係我們一定要搞清楚。
那麼邏輯就是這樣的:
比如說,我想看下 OS 各模組的效能表現,所以執行 top 這個命令看了一些計數器,同時我又知道,網路的資訊在top中是看不到的,所以我要把 OS 大模組看完,還要用netstat看網路,以此類推。
如果你還是覺得這樣不能直接刺激到你的神經,懵懂不知道看哪些命令。那麼在這裡,我用上面的工具給你做一個表格。
命令模組對照表:
有了這些命令墊底之後,下面我們來看常用的監控平臺。
監控平臺 Grafana+Prometheus+node_exporter
這是現在用得比較多的監控平臺了。在微服務時代,再加上 Kubernetes+Docker 的盛行,這個監控套裝幾乎是幹 IT 的都知道。我們來看一下常用的 Dashboard。
為了理解上的通用性,我這裡都用預設的資訊,不用自己定製的。Grafana.com 官方 ID:8919 的模板內容如下:
還記得我們要看系統的模組是哪幾個嗎?
- CPU
- Memory
- I/O
- Network
- System
- Swap
你可以自己對一下,是不是大模組都沒有漏掉?確實沒有。但是!上面的計數器你得理解。
我們先來看一下 CPU。
上圖中有了 System、User、I/O Wait、Total,還記得我們上面說 top 裡有 8 個 CPU 計數器吧,這裡就 4 個怎麼辦?
Total 這個值的計算方式是這樣的:
1 - avg(irate(node_cpu_seconds_total{instance=~"$node",mode="idle"}[30m])) by (instance)
也就是說,它包括除了空閒 CPU 的其他所有 CPU 使用率,這其實就有 ni、hi、si、st、guest、gnice 的值。當我們在這個圖中看到 System、User、I/O Wait 都不高時,如果 Total 很高,那就是 ni、hi、si、st、guest、gnice 計數器中的某個值大了。這時你要想找問題,就得自己執行命令檢視了。
看完 CPU 之後,再看一下 Network。
上圖中有網路流量圖。可以看到只有“上傳下載”,這個值似乎容易理解,但是不夠細緻。node_exportor 還提供了一個“網路連線資訊”圖。可以看到 Sockets_used、CurrEstab、TCP_alloc、TCP_tw、UDP_inuse 這些值,它們所代表的含義如下:
- Sockets_used:已使用的所有協議套接字總量
- CurrEstab:當前狀態為 ESTABLISHED 或 CLOSE-WAIT 的 TCP 連線數
- TCP_alloc:已分配(已建立、已申請到 sk_buff)的 TCP 套接字數量
- TCP_tw:等待關閉的 TCP 連線數
- UDP_inuse:正在使用的 UDP 套接字數量
這些值也可以通過檢視“cat /proc/net/sockstat”知道。這是監控工具套裝給我們提供的便利,然後我們再來看下 Memory。
上圖中有總記憶體、可用記憶體、已用記憶體這三個值。如果從應用的角度來看,我們現在對記憶體的分析,就要和語言相關了。像 Java 語言,一般會去分析 JVM。我們對作業系統的實體記憶體的使用並不關注,在大部分場景下實體記憶體並沒有成為我們的瓶頸點,但這並不是說在記憶體上就沒有調優的空間了。
關於記憶體這一塊,我不想展開太多。因為展開之後內容太多了,如果你有興趣的話,可以找記憶體管理的資料來看看。其他幾個模組我就不再一一列了,I/O、System、Swap 也都是有監控資料的。
從全域性監控的角度上看,這些計數器也基本夠看。但是對於做效能分析、定位瓶頸來說,這些值顯然是不夠的。
還記得我在前面提到的“先全域性監控再定向監控”找證據鏈的理念吧。像 node_exporter 這樣的監控套裝給我們提供的就是全域性監控的資料,就是大面上覆蓋了,細節上仍然不夠。那怎麼辦呢?
下面我就來一一拆解一下。
CPU
關於 CPU 的計數器,已經有很多的資訊了。這裡我再囉嗦一下。CPU 常見的計數器是 top 中的 8 個值,也就是下面這些:
%Cpu(s): 0.7 us, 0.5 sy, 0.0 ni, 98.7 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
含義我就不寫了,你搜一下就會知道。在 mpstat(Multi-Processor Statistics)中看到的是 10 個計數器:
[root@7dgroup3 ~]# mpstat -P ALL 3
Linux 3.10.0-957.21.3.el7.x86_64 (7dgroup3) 12/27/2019 _x86_64_ (2 CPU)
03:46:25 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
03:46:28 PM all 0.17 0.00 0.17 0.00 0.00 0.00 0.00 0.00 0.00 99.66
03:46:28 PM 0 0.33 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 99.67
03:46:28 PM 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
這裡多出來%guest、%gnice兩個值。他們的含義在 Linux man page 中有詳細的說明。
%guest :Show the percentage of time spent by the CPU or CPUs to run a virtual processor.
%gnice:Show the percentage of time spent by the CPU or CPUs to run a niced guest.
你可以看到計數器的名字稍有不同,像top中的wa在mpstat中是%iowait,si是 mpstat 中的%soft。
在 Linux 中,這就是我們經常檢視的 CPU 計數器了。在我的效能生涯中,常見的問題大部分都是體現在這麼幾個計數器上(排名有先後):
- us
- wa
- sy
- si
首先,為了確定看到 CPU 高之後,接著往下分析的方向是絕對沒有錯的,建議你用Perf top -g先看一下 CPU 熱點。
perf預設用的是cpu-clock事件。這一步只是為了確定方向對不對。
那麼如何從這幾個計數器找到後續的證據鏈呢?下面就是我們定向監控分析的過程了。
us CPU 是使用者態程式消耗的 CPU 百分比。大家都知道怎麼往下落。這個鏈就是下面這樣的:
當然不是隻有這幾個命令可以用,你可以找到大把的工具用,我只是列出來常用的。你要是想炫技,可以自己寫些指令碼來做。這個過程幾乎被寫爛了,所以,我就不多餘舉例子了。
wa cpu是 I/O 讀寫等待消耗的 CPU 百分比。這個證據鏈怎麼往下落呢?來看一下。
你看中間有一步跳躍,這就是 wa CPU 直接跳到執行緒了。為什麼沒有程式了呢?那是因為 iotop 有直接到執行緒的能力。如果你想先看程式也可以,記得執行 iotop -P。
sy CPU 是核心消耗的 CPU 百分比。這個問題就有點複雜了,因為它並沒有一個固定的套路。但是它的分析鏈路仍然和 us CPU 高的分析鏈路差不多,只是這個程式可能不是應用的,而是系統自己的。但是,是什麼導致核心程式佔用 CPU 高呢。這可能和應用有關,當然也可能和配置有關。那麼現在我們畫一個它的分析鏈路。
其實在實際的分析過程中,也是這樣的。如果我們看到一個系統的程式消耗了更多的資源,那就要去查一下這個程式是幹嗎的,看它的執行邏輯和配置檔案。
不一定所有情況都是配置的問題,但絕大多數情況是這個原因,只能說,在系統級別,我們遇到的核心程式本身有效能問題的情況還是很少的。大部分時候都只是配置問題。
si CPU 是軟中斷消耗的 CPU 百分比。什麼是軟中斷呢?
簡單點來說,當出現異常或資源爭用時,它是用來管理秩序的。CPU 正在吭哧吭哧著幹活呢,突然來了一個優先順序高的,needs immediate attention,這時就會發一箇中斷訊號給 CPU。
作為一個幹活的,CPU 誰的話都得聽,這時候就把手頭的工作現場儲存一下,幹這個優先順序高的活。除非這個中斷是致命的,不然 CPU 會在幹完這個活之後再回去幹之前的活,這就是一次軟中斷。
個值,越多就越有問題,關鍵是它有多少才是有問題呢?這一點你從來沒有看過有人給建議值對不對?因為它根本沒有可以參考的值,在不同的應用和硬體環境中,si CPU 都會有很大差別。我見過軟中斷每秒幾萬多就有問題的,也見過軟中斷每秒 20 萬都沒有問題的。
下面我來照例畫個分析的圖看一下。
在這個判斷的鏈路中,就是要把 si 的中斷模組找出來,然後再分析這個模組的功能和配置。比如我們看網路卡的中斷,這是常見的一種效能問題。我們要知道網路是頻寬不夠?還是配置得不對?還是防火牆?還是啥啥啥別的原因?
如果是其他的模組也是一樣的邏輯。好,在知道了上面這幾個常見的 CPU 計數器的分析證據鏈邏輯之後,我就不再詳細畫其他的 CPU 的計數器了。
ni 呢,在我職業生涯中就沒見過它高過;hi 倒是見過,不過是因為硬體壞了;st 呢,只有無良商家不斷超賣虛擬伺服器才會出現。如果你在一個企業內部搭建的虛擬化基礎平臺上也經常看見這種情況,那就是公司太窮了,硬體都不夠用。
總結
在作業系統的分析過程中,CPU 絕對是一個重點分析的物件,它的一舉一動都牽動著效能分析的人,所以我們需要在 CPU 的高低上花很多的時間去分析判斷。
幸運的是,當 CPU 使用率高的時候,我們可以有很多的手段來找到對應的根本原因。這個過程不僅分析思路完整,而且工具繁多。它不像網路那麼繞,也不像記憶體那麼複雜,邏輯上還是很清楚的。