效能分析(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 命令檢視系統資源使用情況
- 系統 CPU 使用率(使用者態 us 和核心態 sy )並不高
- 平均負載適中,只有 2 個 R 狀態的程序,無殭屍程序
- 但是軟中斷程序1號(ksoftirqd/1)的 CPU 使用率偏高,而且處理軟中斷的 CPU 佔比已達到 94
- 此外,並無其他異常程序
- 可以猜測,軟中斷就是罪魁禍首
確認是什麼型別的軟中斷
觀察/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 的原理和更多解決思路在後面會講到哦
分析的整體思路
- 系統出現卡頓,執行命令,響應也會變慢
- 通過 top 檢視系統資源情況
- 發現 CPU 使用率(us 和 sy)均不高,平均負載適中,沒有超 CPU 核數的執行狀態的程序,也沒有殭屍程序
- 但是發現處理軟中斷的 CPU 佔比(si)較高,在程序列表也可以看到軟中斷程序 CPU 使用率偏高,猜測是軟中斷導致系統變卡頓的主要原因
- 通過 /proc/sorfirqs 檢視軟中斷型別和變化頻率,發現直接 cat 的話會列印 128 個核的資訊,但只想要兩個核的資訊
- 所以結合 awk 進行過濾,再通過 watch 命令可以動態輸出檢視結果
- 發現有多個軟中斷型別在變化,重點是 NET_RX 變化頻率超高,而且幅度也很大,它是網路資料包接收軟中斷,暫且認為它是問題根源
- 既然跟網路有關係,可以先通過 sar 命令檢視系統網路接收和傳送的整體情況
- 然後可以看到接收的 PPS 會比接收的 BPS 大很多,做下運算,發現網路幀會非常小,也就是常說的小包問題
- 接下來,通過 tcpdump 抓取 80埠的 tcp 協議網路包,會發現大量來自 VM2 傳送的 SYN 包,結合 sar 命令,確認是 SYN FLOOD 攻擊