性能分析(2)- 應用程式 CPU 使用率過高案例
- 2020 年 7 月 30 日
- 筆記
- 性能分析, 測試高級進階技能系列 - 性能分析
性能分析小案例系列,可以通過下面鏈接查看哦
//www.cnblogs.com/poloyy/category/1814570.html
系統架構背景
- 其中一台用作 Web 伺服器,來模擬性能問題
- 另一台用作 Web 伺服器的客戶端,來給 Web 服務增加壓力請求
- 使用兩台虛擬機(均是 Ubuntu 18.04)是為了相互隔離,避免交叉感染
VM2 運行 ab 命令,初步觀察 Nginx 性能
簡單介紹 ab 命令
- ab(apache bench)是一個常用的 HTTP 服務性能測試工具
- 可以向目標伺服器並發發送請求
運行 ab 命令
並發 10 個請求測試 VM1 的 Nginx 性能,總共測試 100 個請求
ab -c 10 -n 10 http://172.20.72.58:10000/
從 ab 的輸出結果可以看到,Nginx 能承受的每秒平均請求數只有 14.73(這也太辣雞了吧)
那到底是哪裡出了問題呢
接下來,我們將通過 top、perf 來再次觀察一波啥問題
深入分析
長時間運行 ab 命令
並發 10 個請求測試 VM1 的 Nginx 性能,總共測試 10000 個請求
ab -c 10 -n 10000 http://172.20.72.58:10000/
VM1 終端運行 top 命令
輸入後,按1,查看每個 CPU 的使用率
- 系統中有幾個 php-fpm 進程的 CPU 使用率加起來接近 200%
- 而每個 CPU 的用戶使用率(us)也已經超過了 96%,接近飽和
- 結論:正是用戶空間的 php-fpm 進程,導致 CPU 使用率驟升
分析 php-fpm 進程到底是因為哪個函數導致了 CPU 使用率升高
在 VM1 終端運行 perf 命令
perf record -g -p 84408
- record:錄製的意思
- -g:開啟調用關係分析
- -p:指定 php-fpm 的進程號84408
錄製約 30s 後,ctrl+c 終止進程,然後可以在當前目錄下看到 perf.data 文件
然後執行下面命令,分析報告(perf.data)
perf report
按方向鍵可上下切換,有+的按回車鍵可以展開
可以看到,最終是關係到 sqrt 和 add_function 這兩個函數
查看 Nginx 應用的源碼,找到問題根源
找到 sqrt 函數
grep sqrt -r app/
原來只有 sqrt 函數在 app/index.php 文件中調用了
找到 add_function 函數
grep add_function -r app/
會發現找不到,因為 add_function 是 PHP 內置函數
查看 index.php 源碼
<?php // test only. $x = 0.0001; for ($i = 0; $i <= 1000000; $i++) { $x += sqrt($x); } echo "It works!"
可以看到,這裡有一個循環很多次的程式碼段
解決方法
找到問題的根源,就可以快速解決了,刪除循環程式碼塊
<?php echo "It works!"
perf 拓展
其實有一條命令更方便查看函數
perf top -g -p 84408
那為啥我要用 perf record 然後再用 perf report 呢
因為如果沒有 perf 源碼的話,是無法讀取到 php 的函數,只會顯示一堆十六進位碼
修復問題後,驗證 Nginx 性能是否有所變化
VM2 終端再次運行 ab 命令
ab -c 10 -n 10000 http://172.20.72.58:10000/
可以看到每秒請求數突飛猛進的升到 2500