性能分析小案例系列,可以通過下面鏈接查看哦
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 攻擊