效能分析(5)- 軟中斷導致 CPU 使用率過高的案例

小菠蘿測試筆記發表於2020-08-11

效能分析小案例系列,可以通過下面連結檢視哦

https://www.cnblogs.com/poloyy/category/1814570.html

 

前言

軟中斷基本原理,可參考這篇部落格:https://www.cnblogs.com/poloyy/p/13435519.html

 

中斷

  • 一種非同步的事件處理機制,用來提供系統的併發處理能力
  • 當中斷事件發生,會觸發執行中斷處理程式
  • 中斷處理程式分為上半部和下半部
  • 上半部:硬中斷,快速處理中斷
  • 下半部:軟中斷,用來非同步處理上半部未完成的工作 

 

軟中斷

  • 每個 CPU 都對應一個軟中斷核心執行緒,名字是 ksoftirqd/CPU 編號
  • 當軟中斷事件的頻率過高時,核心執行緒也會因為 CPU 使用率過高而導致軟中斷處理不及時,進而引發網路收發延遲,排程緩慢等效能問題

                                  

軟中斷頻率過高案例

系統配置

Ubuntu 18.04, 2 CPU,2GB 記憶體,共兩臺虛擬機器

 

三個工具

  • sar:是一個系統活動報告工具,既可以實時檢視系統的當前活動,又可以配置儲存和報告 歷史統計資料。
  • hping3:是一個可以構造 TCP/IP 協議資料包的工具,可以對系統進行安全審計、防火牆 測試等。
  • tcpdump:是一個常用的網路抓包工具,常用來分析各種網路問題

 

虛擬機器關係

 

通過 docker 執行案例

在 VM1 中執行命令

docker run -itd --name=nginx -p 80:80 nginx

 

通過 curl 確認 Nginx 正常啟動

在 VM2 中執行命令

curl http://172.20.72.58/

 

通過 hping3 模擬 Nginx 的客戶端請求

在 VM2 中執行命令

hping3 -S -p 80 -i u100 172.20.72.58
  • -S:參數列示設定 TCP 協議的 SYN(同步序列號)
  • -p:表示目的埠為 80
  • -i:u100 表示每隔 100 微秒傳送一個網路幀

 

回到 VM1

感覺系統響應明顯變慢了,即便只 是在終端中敲幾個回車,都得很久才能得到響應

 

分析系統為什麼會響應變慢

以下命令均在 VM1 中執行

 

通過 top 命令檢視系統資源使用情況

  1. 系統 CPU 使用率(使用者態 us 和核心態 sy )並不高 
  2. 平均負載適中,只有 2 個 R 狀態的程式,無殭屍程式
  3. 但是軟中斷程式1號(ksoftirqd/1)的 CPU 使用率偏高,而且處理軟中斷的 CPU 佔比已達到 94
  4. 此外,並無其他異常程式
  5. 可以猜測,軟中斷就是罪魁禍首

 

確認是什麼型別的軟中斷

觀察 /proc/softirqs 檔案的內容,就能知道各種軟中斷型別的次數

 

這裡的各類軟中斷次數,又是什麼時間段裡的次數呢?

  • 它是系統執行以來的累積中斷次數
  • 所以直接檢視檔案內容,得到的只是累積中斷次數,對這裡的問題並沒有直接參考意義
  • 中斷次數的變化速率才是我們需要關注的

 

通過 watch 動態檢視命令輸出結果

因為我的機器是兩核,如果直接讀取 /proc/softirqs 會列印 128 核的資訊,但對於我來說,只要看前面兩核的資訊足以,所以需要寫提取關鍵資料

watch -d "/bin/cat /proc/softirqs | /usr/bin/awk 'NR == 1{printf \"%-15s %-15s %-15s\n\",\" \",\$1,\$2}; NR > 1{printf \"%-15s %-15s %-15s\n\",\$1,\$2,\$3}'"

結果分析

  • TIMER(定時中斷)、 NET_RX(網路接收)、SCHED(核心排程)、RCU(RCU 鎖)等這幾個軟中斷都在不停變化
  • NET_RX,就是網路資料包接收軟中斷變化速率最快
  • 其他幾種型別的軟中斷,是保證 Linux 排程、時鐘、臨界區保護這些正常工作所必需的,所以有變化時正常的

 

通過 sar 檢視系統的網路收發情況

上面確認了從網路接收的軟中斷入手,所以第一步應該要看下系統的網路接收情況

 

sar 的好處

  • 不僅可以觀察網路收發的吞吐量(BPS,每秒收發的位元組數)
  • 還可以觀察網路收發的 PPS(每秒收發的網路幀數)

 

執行 sar 命令

sar -n DEV 1

  • 第二列:IFACE 表示網路卡
  • 第三、四列:rxpck/s 和 txpck/s 分別表示每秒接收、傳送的網路幀數【PPS】
  • 第五、六列:rxkB/s 和 txkB/s 分別表示每秒接收、傳送的千位元組數【BPS】

 

結果分析

對網路卡 ens33 來說

  • 每秒接收的網路幀數比較大,幾乎達到 8w,而傳送的網路幀數較小,只有接近 4w
  • 每秒接收的千位元組數只有 4611 KB,傳送的千位元組數更小,只有2314 KB

 

docker0 veth04076e3

  • 資料跟 ens33 基本一致只是傳送和接收相反,傳送的資料較大而接收的資料較小
  • 這是 Linux 內部網橋轉發導致的,暫且不用深究,只要知道這是系統把 ens33 收到的包轉發給 Nginx 服務即可

 

異常點

  • 前面說到是網路資料包接收軟中斷的問題,那就重點看 ens33
  • 接收的 PPS 達到 8w,但接收的 BPS 只有 5k 不到,網路幀看起來是比較小的
  • 4611 * 1024 / 78694 = 64 位元組,說明平均每個網路幀只有 60 位元組,這顯然是很小的網路幀,也就是常說的小包問題

 

靈魂拷問

如何知道這是一個什麼樣的網路幀,它又是從哪裡發過來的呢?

 

通過 tcpdump 抓取網路包

已知條件

Nginx 監聽在 80 埠, 它所提供的 HTTP 服務是基於 TCP 協議的

 

執行 tcpdump 命令

tcpdump -i ens33 -n tcp port 80
  • -i ens33:只抓取 ens33 網路卡
  • -n:不解析協議名和主機名
  • tcp port 80:表示只抓取 tcp 協議並且埠號為 80 的網路幀

172.20.72.59.52195 > 172.20.72.58.80

  • 表示網路幀從 172.20.72.59 的 52195 埠發 送到 172.20.72.58 的 80 埠
  • 也就是從執行 hping3 機器的 52195 埠傳送網路幀, 目的為 Nginx 所在機器的 80 埠

 

Flags [S]

表示這是一個 SYN 包

 

效能分析結果

結合 sar 命令發現的 PPS 接近 4w 的現象,可以認為這就是從 172.20.72.59 這個地址傳送過來的 SYN FLOOD 攻擊

 

解決 SYN FLOOD 問題

從交換機或者硬體防火牆中封掉來源 IP,這樣 SYN FLOOD 網路幀就不會傳送到伺服器中

 

後續的期待

至於 SYN FLOOD 的原理和更多解決思路在後面會講到哦

 

分析的整體思路

  1. 系統出現卡頓,執行命令,響應也會變慢
  2. 通過 top 檢視系統資源情況
  3. 發現 CPU 使用率(us 和 sy)均不高,平均負載適中,沒有超 CPU 核數的執行狀態的程式,也沒有殭屍程式
  4. 但是發現處理軟中斷的 CPU 佔比(si)較高,在程式列表也可以看到軟中斷程式 CPU 使用率偏高,猜測是軟中斷導致系統變卡頓的主要原因
  5. 通過 /proc/sorfirqs 檢視軟中斷型別和變化頻率,發現直接 cat 的話會列印 128 個核的資訊,但只想要兩個核的資訊
  6. 所以結合 awk 進行過濾,再通過 watch 命令可以動態輸出檢視結果
  7. 發現有多個軟中斷型別在變化,重點是 NET_RX 變化頻率超高,而且幅度也很大,它是網路資料包接收軟中斷,暫且認為它是問題根源
  8. 既然跟網路有關係,可以先通過 sar 命令檢視系統網路接收和傳送的整體情況
  9. 然後可以看到接收的 PPS 會比接收的 BPS 大很多,做下運算,發現網路幀會非常小,也就是常說的小包問題
  10. 接下來,通過 tcpdump 抓取 80埠的 tcp 協議網路包,會發現大量來自  VM2 傳送的 SYN 包,結合 sar 命令,確認是 SYN FLOOD 攻擊

相關文章