https://moonbingbing.gitbooks.io/openresty-best-practices/flame_graph/how.html
一個正常的火焰圖,應該呈現出如官網給出的樣例(官網的火焰圖是抓 C 級別函數):
從上圖可以看出,正常業務下的火焰圖形狀類似的“山脈”,“山脈”的“海拔”表示 worker 中業務函數的調用深度,“山脈”的“長度”表示 worker 中業務函數佔用 cpu 的比例。
下面將用一個實際應用中遇到問題抽象出來的示例(CPU 佔用過高)來說明如何通過火焰圖定位問題。
問題表現,Nginx worker 運行一段時間後出現 CPU 佔用 100% 的情況,reload 後一段時間後復現,當出現 CPU 佔用率高情況的時候是某個 worker 佔用率高。
問題分析,單 worker cpu 高的情況一定是某個 input 中包含的信息不能被 Lua 函數以正確地方式處理導致的,因此上火焰圖找出具體的函數,抓取的過程需要抓取 C 級別的函數和 Lua 級別的函數,抓取相同的時間,兩張圖一起分析才能得到準確的結果。
抓取步驟:
- 安裝SystemTap
-
獲取 CPU 異常的 worker 的進程 ID :
ps -ef | grep nginx
-
使用 lj-lua-stacks.sxx抓取棧信息,並用 fix-lua-bt 工具處理:
# making the ./stap++ tool visible in PATH: $ export PATH=$PWD:$PATH # assuming the nginx worker process pid is 6949: $ ./samples/lj-lua-stacks.sxx --arg time=5 --skip-badvars -x 6949 > tmp.bt Start tracing 6949 (/opt/nginx/sbin/nginx) Please wait for 5 seconds $ ./fix-lua-bt tmp.bt > a.bt
-
使用 stackcollapse-stap.pl 和 flamegraph.pl:
./stackcollapse-stap.pl a.bt > a.cbt ./flamegraph.pl a.cbt > a.svg
-
a.svg 即是火焰圖,拖入瀏覽器即可:
-
從上圖可以清楚的看到 get_serial_id 這個函數佔用了絕大部分的 CPU 比例,問題的排查可以從這裏入手,找到其調用棧中異常的函數。
PS:一般來說一個正常的火焰圖看起來像一座座連綿起伏的“山峯”,而一個異常的火焰圖看起來像一座“平頂山”。