1. 程式人生 > >Linux性能優化實戰:系統的軟中斷CPU使用率升高,我該怎麽辦?(10)

Linux性能優化實戰:系統的軟中斷CPU使用率升高,我該怎麽辦?(10)

工具 true 即使 硬中斷 休息 gin pcap 網卡流量 指定

一、壞境準備

1、拓撲圖

技術分享圖片

2、安裝包

在第9節的基礎上

在VM2上安裝hping3依奈包

wget http://www.tcpdump.org/release/libpcap-1.9.0.tar.gz
tar xf libpcap-1.9.0.tar.gz
cd libpcap-1.9.0/
./configure && make && make install
[[email protected] pcap]# pwd
/root/libpcap-1.9.0/pcap
[[email protected] pcap]# cp -a bpf.h /usr/include/net/bpf.h

在VM2上安裝hping3的安裝

yum install gcc libpcap-devel   tcl-devel -y
git clone https://github.com/antirez/hping.git
cd hping
./configure && make

3、實驗環境準備

1、運行案例終端一

[[email protected] ~]# docker run -itd --name=nginx -p 80:80 nginx
docker: Error response from daemon: Conflict. The container name "/nginx" is already in use by container "f78d08880b62aa97fbbd8b3a545af4bcd849b05ecca7493874028fcaffaffc41". You have to remove (or rename) that container to be able to reuse that name.
See ‘docker run --help‘.
[[email protected] ~]# docker ps -l
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS                     PORTS               NAMES
cf7abb7672d9        feisky/app:iowait-fix2   "/app"              25 hours ago        Exited (255) 5 hours ago

[[email protected] ~]# docker rm -f app
app
[[email protected] ~]# docker run -itd --name=nginx -p 80:80 nginx
6545b4661b2f3c8ef0eba73706c2d1bf7a0b5469272b77ed172a4f4b92b068b9

2、確認nginx正常啟動(終端二)

curl http://192.168.118.97/

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

3、運行 hping3 命令,來模擬 Nginx 的客戶端請求(終端二)

[[email protected] hping]# pwd
/root/hping
# -S 參數表示設置 TCP 協議的 SYN(同步序列號),-p 表示目的端口為 80
# -i u100 表示每隔 100 微秒發送一個網絡幀
# 註:如果你在實踐過程中現象不明顯,可以嘗試把 100 調小,比如調成 10 甚至 1
[[email protected] hping]# ./hping3 -S -p 80 -i u100 192.168.118.97
HPING 192.168.118.97 (eth0 192.168.118.97): S set, 40 headers + 0 data bytes
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=0 win=29200 rtt=34.8 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=1 win=29200 rtt=37.4 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=2 win=29200 rtt=36.1 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=3 win=29200 rtt=35.5 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=4 win=29200 rtt=34.1 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=5 win=29200 rtt=32.2 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=6 win=29200 rtt=31.7 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=7 win=29200 rtt=30.6 ms
len=46 ip=192.168.118.97 ttl=63 DF id=0 sport=80 flags=SA seq=8 win=29200 rtt=1027.6 ms
...

二、分析過程

1、查看系統整體的資源使用情況(終端一)

# top 運行後按數字 1 切換到顯示所有 CPU
top - 16:51:32 up 4:54, 2 users, load average: 0.01, 0.03, 0.05
Tasks: 103 total, 2 running, 101 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 78.7 id, 0.0 wa, 0.0 hi, 21.2 si, 0.0 st
KiB Mem : 8056848 total, 7167580 free, 399752 used, 489516 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 7327620 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14 root 20 0 0 0 0 R 3.0 0.0 8:14.97 ksoftirqd/1
9 root 20 0 0 0 0 S 1.0 0.0 2:10.35 rcu_sched
9395 root 20 0 419132 32876 14612 S 1.0 0.4 5:19.33 containerd
9753 mysql 20 0 1119708 182720 5796 S 0.7 2.3 1:25.85 mysqld
7508 root 20 0 227036 6348 4944 S 0.3 0.1 1:09.48 vmtoolsd
16355 root 20 0 0 0 0 S 0.3 0.0 0:00.39 kworker/0:1
16358 root 20 0 161996 2224 1564 R 0.3 0.0 0:00.09 top
1 root 20 0 43640 4024 2552 S 0.0 0.0 0:03.60 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.04 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:03.80 ksoftirqd/0
...

根據上一期的內容,既然軟中斷可能有問題,那你先要知道究竟是哪類軟中斷的問題?

1、是系統運行以來的累積中斷次數

不過,這裏的各類軟中斷次數,又是什麽時間段裏的次數呢?它是系統運行以來的累積中斷次數

所以我們直接查看文件內容,得到的只是累積中斷次數,對這裏的問題並沒有直接參考意義,因為這些中斷次數的變化速率才是我們需要關註的

2、觀察各種軟中斷類型的次數(終端一)

[[email protected] ~]# watch -d cat /proc/softirqs		 
                    CPU0       CPU1      		 
          HI:          1          0      		 
       TIMER:     928050    4221133      		 
      NET_TX:       2670         12      		 
      NET_RX:        102   24694097      		 
       BLOCK:      13635          0      		 
BLOCK_IOPOLL:          0          0      	
     TASKLET:         56       1535      
       SCHED:     477868    1155566      
     HRTIMER:          0          0      
         RCU:     747103    1976371  

1、通過/proc/softirqs 文件內容的變化情況,你可以發現, TIMER(定時中斷)、NET_RX(網絡接收)、SCHED(內核調度)、RCU(RCU 鎖)等這幾個軟中斷都在不停變化。

2、其中NET_RX,也就是網絡數據包接收軟中斷的變化速率最快。而其他幾種類型的軟中斷,是保證 Linux 調度、時鐘和臨界區保護這些正常工作所必需的,所以它們有一定的變化倒是正常的。

那麽接下來,我們就從網絡接收的軟中斷著手,繼續分析,既然是網絡接收的軟中斷,第一步應該是觀察系統的網絡接收情況。這裏你可能想起很多網絡工具,不過我推薦今天的主人工sar

3、觀察系統的網絡接收情況(終端一)

sar可以用來查看系統的網絡首發情況,還有一個好處,不可以觀察網絡收發的吞吐量(BPS,每秒收發的字節數),還可以觀察網絡收發的PPS,即每秒收發的網絡幀數

# -n DEV 表示顯示網絡收發的報告,間隔 1 秒輸出一組數據
[[email protected] ~]# sar -n DEV 1
Linux 3.10.0-957.5.1.el7.x86_64 (luoahong) 	05/06/2019 	_x86_64_	(2 CPU)

03:39:02 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
03:39:03 PM br-ad2616372f01      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
03:39:03 PM      eth0   4456.00   2231.00    261.09    130.85      0.00      0.00      0.00      0.21
03:39:03 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
03:39:03 PM veth502c523   2227.00   4456.00    126.14    234.98      0.00      0.00      0.00      0.02
03:39:03 PM   docker0   2227.00   4456.00     95.69    234.98      0.00      0.00      0.00      0.00

03:39:03 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
03:39:04 PM br-ad2616372f01      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
03:39:04 PM      eth0   4392.00   2190.00    257.34    128.99      0.00      0.00      0.00      0.21
03:39:04 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
03:39:04 PM veth502c523   2190.00   4380.00    124.04    230.98      0.00      0.00      0.00      0.02
03:39:04 PM   docker0   2190.00   4380.00     94.10    230.98      0.00      0.00      0.00      0.00

sar命令圖解

技術分享圖片

我們具體來看輸出的內容,你可以發現:每秒接收的網絡幀數遠大於發送的網絡幀數

既然懷疑是網絡中斷的問題,我們還是重點來看eth0接收的BPS很小,稍微計算一下,說明平均每個網絡幀數只有54字節,這顯然是很小的網絡幀,這也就是我們通常所說的小包問題

4、這是一個什麽樣的網絡幀?從哪裏發過來的呢?(終端一)

那麽,有沒有辦法知道這是一個什麽樣的網絡幀,以及從哪裏發過來的呢?

# -i eth0 只抓取 eth0 網卡,-n 不解析協議名和主機名
# tcp port 80 表示只抓取 tcp 協議並且端口號為 80 的網絡幀
$ tcpdump -i eth0 -n tcp port 80
15:37:44.411911 IP 192.168.118.105.64379 > 192.168.118.97.http: Flags [R], seq 1503793557, win 0, length 0
15:37:44.411919 IP 192.168.118.105.64380 > 192.168.118.97.http: Flags [R], seq 395003338, win 0, length 0
15:37:44.413313 IP 192.168.118.105.64382 > 192.168.118.97.http: Flags [S], seq 1080244426, win 512, length 0
15:37:44.413335 IP 192.168.118.105.64381 > 192.168.118.97.http: Flags [R], seq 176434656, win 0, length 0
15:37:44.413340 IP 192.168.118.105.64383 > 192.168.118.97.http: Flags [S], seq 2026187932, win 512, length 0
15:37:44.413347 IP 192.168.118.105.64384 > 192.168.118.97.http: Flags [S], seq 860129571, win 512, length 0
15:37:44.413431 IP 192.168.118.97.http > 192.168.118.105.64382: Flags [S.], seq 2546910072, ack 1080244427, win 29200, options [mss 1460], length 0
15:37:44.413547 IP 192.168.118.97.http > 192.168.118.105.64383: Flags [S.], seq 1083250845, ack 2026187933, win 29200, options [mss 1460], length 0
15:37:44.413604 IP 192.168.118.97.http > 192.168.118.105.64384: Flags [S.], seq 3306737583, ack 860129572, win 29200, options [mss 1460], length 0
15:37:44.417237 IP 192.168.118.105.64385 > 192.168.118.97.http: Flags [S], seq 311506147, win 512, length 0
...

從tcpdump的輸出中,你可以發現

1、192.168.118.105.64382 > 192.168.118.97 表示網絡幀從192.168.118.105的64382端口到192.168.118.97的80端口,也就是運行hping3 機器的 64379 端口發送網絡幀,

2、目的位Nginx所在機器的80端口

3、Flags [S] 則表示這是一個 SYN 包

再加上前面用 sar 發現的, PPS 超過 12000 的現象,現在我們可以確認,這就是從192.168.118.105 這個地址發送過來的SYN FLOOD 攻擊

三、小結

到這裏,我們已經做了全套的性能診斷和分析。

1、從系統的軟中斷使用率高這個現象出發,

2、通過觀察/proc/softirqs 文件的變化情況,判斷出軟中斷類型是網絡接收中斷

3、再通過 sar 和 tcpdump ,確認這是一個 SYN FLOOD問題

4、SYN FLOOD 問題最簡單的解決方法,就是從交換機或者硬者硬件防火墻中封掉來源 IP,這樣 SYN FLOOD 網絡絡幀就不會發送到服務器中

軟中斷CPU使用率升高是一種很常見的性能問題,雖然軟中斷的類型很多,但實際生產中,我們遇到的性能瓶頸大多數是網絡收發類型的軟中斷,特別是網絡接收的軟中

在碰到這類問題時,你可以借用sar、tcpdump等工具,做進一步分析,不要害怕網絡性能,後面我們會教你更多的分析方法

四、思考題

1、你所碰到的軟中斷問題。

我的理解比較簡單粗暴, 硬中斷是硬件產生的,比如鍵盤、鼠標的輸入,硬盤的寫入讀取、網卡有數據了;軟中斷是軟件產生的,比如程序內的定時器、[文中提到的RCU鎖]。
再加上今天的上半部下半部,更好的理解了網卡的處理實際是有硬中斷和軟中斷的。

2、你所碰到的軟中問題是哪種類型

有,且是血淋淋的教訓。
之前的c程序用到了別人寫的動態庫[如:lib.a],在物理機上,進程的cpu利用率在0%;而切換到了雲服務器,即使空載,單進程的cpu利用率都有30%+。
以前沒經驗嘛,各種自查,無結果,但是自己的進程cpu利用率又那麽高,總是不安心.
後來才通過vmstat 檢測到系統的軟中斷每秒有100W+次.
最後各自百度,找人,才發現是那個動態庫在處理網絡收發消息時,使用了usleep(1)來休息,每次休息1納秒,單次中斷的耗時都不止1納秒.

3、是不是這個案例中的小包問題?

如果是現在,我會如下分析:

1.檢測是哪個線程占用了

cpu: top -H -p XX 1 / pidstat -wut -p XX 1

2.在進程中打印各線程號. 找到是哪個線程.[ 此過程也可以省略 但可以快速定位線程]

3.第一步應該可以判斷出來中斷數過高. 再使用 cat /proc/softirqs 查看是哪種類型的中斷數過高.

4.不知道perf report -g -p XX 是否可以定位到具體

5.最終還是要查看源碼,定位具體的位置,並加以驗證.

4、你又是怎麽分析它們的來源並解決的呢?

本期又學到新東西了:
1.sar 原來可以這麽方便的看各網卡流量,甚至是網絡幀數.

到目前為止,我都是用的最原始的方法:在網上找的一個腳本,分析ifconfig中的數據,來統計某個網卡的流量.一來需要指定某個網卡(默認eth0),二來顯示的數據不太準確且不友好(sleep 1做差值).

2.nping3 居然可以用來模擬SYN FLOOD. (不要用來做壞事哦)

3.tcpdump 之前有所耳聞. 用的不多. 平常有解包需求,都是在windows下用wireshark,畢竟是圖形界面.

Linux性能優化實戰:系統的軟中斷CPU使用率升高,我該怎麽辦?(10)