注:本文操作基於CentOS 系統
准備工作
- 用wget從https://sourceware.org/systemtap/ftp/releases/下載最新版的systemtap.tar.gz壓縮包,然后解壓、./configure; make; make install 安裝到目標主機;執行命令
stap -ve 'probe begin { log("hello systemtap!") exit() }'如果提示pass 5: run completed ... 就表示安裝成功。 - 安裝內核開發包、調試包(需要查看內核函數)yum install kernel-devel; yum install kernel-debuginfo (需要觀察內核級函數時)。
- 用wget從https://github.com/openresty/nginx-systemtap-toolkit下載最新的openresty調試工具,然后解壓到/opt即可。
- 用wget從https://github.com/brendangregg/FlameGraph下載最新的FlameGraph(火焰圖),然后解壓到/opt即可。
開始測試
- 配置openresty中的worker_processes、worker_cpu_affinity,然后啟動openresty。
- 利用壓測工具開始向openresty起壓,統計QPS變化。
- 使用如下腳本生成火焰圖(注:該腳本需要三個參數:分析的對象c表示nginx部分、lua表示lua腳本部分, PID是要分析的一個worker進程, NAME是生成火焰圖的名稱) 大家可以根據自己的實際環境對腳本進行修改
#!/bin/sh
if [ $# -ne 3 ]
then
echo "Usage: ./`basename $0` lua/c PID NAME"
exit
fi
pid=$2
name=$3
if [ $1 == "lua" ]
then
/opt/nginx-systemtap-toolkit/ngx-sample-lua-bt -p $pid --luajit20 -t 30 >temp.bt
/opt/nginx-systemtap-toolkit/fix-lua-bt temp.bt >${name}.bt
elif [ $1 == "c" ]
then
/opt/nginx-systemtap-toolkit/sample-bt -p $pid -t 10 -u > ${name}.bt
else
echo "type is only lua/c"
exit
fi
/opt/FlameGraph/stackcollapse-stap.pl ${name}.bt >${name}.cbt
/opt/FlameGraph/flamegraph.pl ${name}.cbt >${name}.svg
rm -f temp.bt ${name}.bt ${name}.cbt
火焰圖分析:
附上一張openresty C部分nginx的火焰圖
火焰圖上下表示函數調用棧(類似於gdb中bt命令看到的棧幀順序),可以通過函數調用棧來定位到具體的執行路徑;每一個函數的寬度表示該函數占用的cpu時間片,可以重點分析占用cpu時間片過多的函數。
后記:
openresty提供的性能分析工具基於systemtap。systemtap 的核心思想是定義一個事件(event),以及給出處理該事件的句柄(Handler)。當一個特定的事件發生時,內核運行該處理句柄,就像快速調用一個子函數一樣,處理完之后恢復到內核原始狀態。這里有兩個概念:
- 事件(Event):systemtap 定義了很多種事件,例如進入或退出某個內核函數、定時器時間到、整個systemtap會話啟動或退出等等。
- 句柄(Handler):就是一些腳本語句,描述了當事件發生時要完成的工作,通常是從事件的上下文提取數據,將它們存入內部變量中,或者打印出來。
systemtap 工作原理是通過將腳本語句翻譯成C語句,編譯成內核模塊。模塊加載之后,將所有探測的事件以鈎子的方式掛到內核上,當任何處理器上的某個事件發生時,相應鈎子上句柄就會被執行。最后,當systemtap會話結束之后,鈎子從內核上取下,移除模塊。整個過程用一個命令 stap 就可以完成。
