性能分析(2)- 應用程序 CPU 使用率過高案例


性能分析小案例系列,可以通過下面鏈接查看哦

https://www.cnblogs.com/poloyy/category/1814570.html

 

系統架構背景

  • VM1:用作 Web 服務器,來模擬性能問題
  • VM2:用作 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(這也太辣雞了吧)

 

那到底是哪里出了問題呢

接下來,我們將通過一系列的命令來觀察哪里出問題了

 

深入分析

VM2 長時間運行 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

 

按方向鍵可上下切換,有+的按回車鍵可以展開

結果分析

最終是關系到 sqrtadd_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,比之前的 14 好多了

 

分析整體思路

  1. 使用 ab 短時間壓測,發現服務器性能低下,TPS 比較低
  2. 使用 ab 長時間壓測,讓服務器保持一個高負載的狀態,方便排查問題
  3. 通過 top 命令監控系統資源情況,發現用戶態的 CPU 使用率(us)很高,且進程列表中發現幾個進程的 CPU 使用率特別高,都是同一個 php 進程
  4. 通過 perf record 命令錄制進程一段時間
  5. 通過 perf report 查看錄制進程的結果數據,可以分析 php-fpm 進程到底是哪個函數導致 CPU 使用率高
  6. 找到 add_function、sqrt 函數
  7. 通過 grep 命令確認函數是在 index.php 代碼文件中
  8. 查看 index.php 文件的源碼,確認問題代碼塊
  9. 刪除問題代碼塊,重新壓測,每秒平均請求數有了質的飛升,成功解決問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM