案例:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

chenlixin發表於2020-01-09

記錄課程實踐過程,推薦前往 Linux 效能優化筆記 學習更多。:fire:

環境準備

  • 兩臺虛擬機器(Ubuntu 18.04)
  • 機器配置:2 CPU,8GB 記憶體
  • 預先安裝 docker、sysstat、perf、ab 等工具,如 apt install docker.io sysstat linux-tools-common apache2-utils

操作和分析

其中一臺用作 Web 伺服器,來模擬效能問題;另一臺用作 Web 伺服器的客戶端,來給 Web 服務增加壓力請求。

開啟兩個終端,分別 SSH 登入到兩臺機器上,並安裝上面提到的工具。

預設以 root 使用者執行所有命令,先執行 sudo su root 命令切換到 root 使用者。

由於 Nginx 和 PHP 的配置比較麻煩, 課程提供了兩個Docker 映象,這樣只需要執行兩個容器,就可以得到模擬環境。

執行docker容器應用

首先,在第一個終端執行下面的命令來執行 Nginx 和 PHP 應用:

$ docker run --name nginx -p 10000:80 -itd feisky/nginx
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm

下載過程可能比較緩慢...下載完成後,執行 docker ps -a ,如圖:

案例練習:某個應用的CPU使用率居然達到100%,我該怎麼辦?

第二個終端使用 curl 訪問 http://[VM1 的 IP]:10000,確認 Nginx 已正常啟動。

# 192.168.139.139是第一臺虛擬機器的IP地址
$ curl http://192.168.139.139:10000/

如圖:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

壓力測試一

在第二個終端執行下面的 ab 命令:

# 併發10個請求測試Nginx效能,總共測試100個請求
$ ab -c 10 -n 100 http://192.168.139.139:10000/

如圖:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?
從 ab 的輸出結果我們可以看到,Nginx 能承受的每秒平均請求數只有 11.47。這個資料實際是很差的,如果暫時感覺不到什麼,那嘗試用 toppidstat 再做觀察。

壓力測試二

繼續在第二個終端,執行 ab 命令:

# 這次將測試的請求總數增加到10000
$ ab -c 10 -n 10000  http://192.168.139.139:10000/

回到第一個終端執行 top 命令,並按下數字 1 ,切換到每個 CPU 的使用率:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

這裡可以看到,系統中有幾個 php-fpm 程式的 CPU 使用率加起來接近 100%;而 CPU 的使用者使用率(us)也已經超過了 99%,接近飽和。這裡猜測是使用者空間的 php-fpm 程式,導致 CPU 使用率驟升。

perf 分析 php-fpm 程式

那怎麼知道是 php-fpm 的哪個函式導致了 CPU 使用率升高呢?我們來用 perf 分析一下。

在第一個終端執行下面的 perf 命令(如果提示命令not found,按提示安裝即可):

# -g開啟呼叫關係分析,-p指定php-fpm的程式號2250
$ perf top -g -p 2250

如圖:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

通過方向鍵移動到 php-fpm 程式,通過 enter 鍵展開 + 號位置的內容,如圖:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

可以看到,呼叫關係最終到了 sqrt 和 add_function。

grep 查詢具體函式

嘗試將PHP原始碼拷貝出來,然後檢視是不是呼叫了這兩個函式,

# 從容器phpfpm中將PHP原始碼拷貝出來
$ docker cp phpfpm:/app .

# 使用grep查詢函式呼叫
$ grep sqrt -r app/ #找到了sqrt呼叫
$ grep add_function -r app/ #沒找到add_function呼叫,這其實是PHP內建函式

如圖:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

到這裡可知,只有 sqrt 函式在 app/index.php 被呼叫。最後我們來看下這個檔案原始碼,

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

其實,這裡的本意,//test only 下的程式碼是不應該存在的,因為它造成多餘地消耗CPU。程式碼雖然簡單,但我們還是嘗試把測試程式碼刪除,再看看執行效果吧。

優化應用程式碼

課程提供了一個優化後的映象,可以如下操作:

# 停止原來的應用
$ docker rm -f nginx phpfpm
# 執行優化後的應用
$ docker run --name nginx -p 10000:80 -itd feisky/nginx:cpu-fix
$ docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:cpu-fix

不過,我想直接在現有容器上修改,修改已經拷貝出來的 index.php

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

然後覆蓋到php-fpm容器裡面,並驗證是否更新了程式碼,

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

壓力測試三

確保終端一正常執行 Nginx 和 PHP 應用,切換到終端二,首先 Ctrl+C 停止之前的 ab 命令後,再執行下面的命令:

ab -c 10 -n 10000  http://192.168.139.139:10000/

如圖:

案例練習:某個應用的 CPU 使用率居然達到 100%,我該怎麼辦?

可以看到,現在每秒的平均請求數,已經從原來的 11 變成了 1222。

結語

本案例程式碼設計較為簡單,工作中可能遇到更加複雜的問題,這裡只是分享下,一種查詢發現問題的方法。

高手勿噴,喜歡的朋友們也請點個贊吧。後續有機會再分享其他案例。:smile:

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章