春哥的nginx systemtap除錯指令碼簡單介紹
阿新 • • 發佈:2019-01-05
因為一直在ubuntu上使用,所以安裝很簡單 sudo apt-get installsystemtap,原始碼安裝的話請參考這篇文章:http://www.cnblogs.com/hazir/p/systemtap_introduction.html中的方法一。
二、核心除錯資訊
不用跟蹤核心態效能大概也不需要,不過保不齊會用到所以我也把核心除錯資訊搞上了。對於ubuntu這種發行版核心來說好處是官方已經提供了(URL:http://ddebs.ubuntu.com/pool/main/l/linux/),根據自己的核心(uname-a 查詢)挑選版本。 如我的是Linux ubuntu 3.13.0-32-generic那麼對應的就是:linux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb。
下載後用 dpkg -ilinux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb安裝。
三、Hello Systemtap!
上面這些完成以後可以使用命令:sudo stap -ve 'probe begin { log("hello Systemtap!")exit() }' 來測試是否安裝成功。如果成功的話會有類似下面的輸出:
四、nginx-systemtap-toolkit
進入正題,這個就是主要介紹的章亦春大神寫的systemtap nginx除錯的系列指令碼了(URL:Github地址),提供了活動請求的查詢、ngx_lua模組的當前lua堆疊檢視、pcre模式串/執行時間分析、C堆疊取樣等等炸裂功能。
首先介紹下C堆疊取樣這個指令碼,結合Brendan Gregg大神寫的FlameGraph tools(URL:https://github.com/brendangregg/FlameGraph),可以畫出功能實用、看著酷炫的火焰圖。如圖:
這個東西的原理就是在程式執行的時候每隔一定的時間對指定程序的C堆疊進行取樣,將當前各棧幀的函式名儲存起來。因為取樣時間是恆定的,所以最後的結果上如果一個函式佔用cpu時間越長,那麼得到的取樣次數也就越多,最後反映到火焰圖上的橫軸長度就越長。另外顏色深淺其實沒什麼含義,只是方便檢視。
使用方法:
1、首先確定編譯的程式碼要帶有除錯i資訊,以便除錯指令碼可以獲得具體的程式碼資訊。如nginx就要加上--with-debug開關。
2、其次要調優的程序已經啟動,並且獲得其pid,對於nginx這種多程序的程式,需要找到一個worker程序的pid,所以如果是開發環境調優的話,可以考慮使用單程序跑nginx。
3、命令sudo ./nginx-systemtap-toolkit/sample-bt -p 1147 -u -t 20 >trace.txt
其中-p 指定程序的pid
-u 追蹤使用者態的呼叫堆疊(也可以使用-k追蹤程式執行期間在核心態的堆疊)
-t 指令碼的執行時間,達到時間之後指令碼自動停止,將堆疊資訊輸出,單位為秒
啟動後會有類似的資訊:
WARNING: Tracing 1147 (/home/kawaru/nginx/sbin/nginx) in user-spaceonly...
提示已經開始跟蹤,這是可以用ab等等東西打點流量,等20秒之後會顯示:
WARNING: Time's up. Quitting now...(it may take a while)
這時候有可能需要多等一會,成功完成後會在trace.txt裡看到類似
一堆堆疊資訊。
4、製作火焰圖,這時就需要用到flame graph tools了,一共分為兩步:
一個是根據不同工具生成的堆疊資訊轉化為一個呼叫計數結果,因為我們用的是systemtap生成的,所以使用stackcollapse-stap.pl這個指令碼,命令如下:
./FlameGraph/stackcollapse-stap.pl ./trace.txt > trace.out
之後再使用flamegraph.pl生成最終的svg格式的火焰圖,命令:
./FlameGraph/flamegraph.pl ./trace.out > trace.svg
最後就可以看到瀏覽器裡開啟trace.svg,看到酷炫的火焰圖了:
上面介紹的是sample-bt這個指令碼,比較適用於cpu佔用較高時對低效程式碼的排查,如果cpu佔用不高,但執行的效率還是很低可以考慮是否是阻塞在io上,這時可以使用sample-bt-off-cpu這個指令碼,檢視io阻塞在哪段程式碼上,以便著手優化,使用方法差不多就不單獨介紹了。
另外一個比較實用的是ngx-pcre-stats 這個,可以追蹤nginx執行過程中跑pcre正則的效能,具體使用:
sudo ./ngx-pcre-stats -p 11276 --total-time-top --luajit20
-p 程序pid
--luajit20 根據系統裡用的是lua5.1還是luajit2.0分別使用--lua51或者--luajit20
--total-time-top 追蹤時的針對的專案,一共有四個除了total-time-top這個追蹤單個正則總計執行時間外,還有--exec-time-dist:檢視正則執行時間分佈,--worst-time-top,執行時間最差情況的十條正則;--data-len-dist正則匹配時匹配串的長度分佈。這四個專案每次執行時候選擇一個使用。
-t 跟蹤時間,單位為秒,不指定的話ctrl-c結束。
使用效果:
可以看出最差情況下第一條執行時間消耗比較多,這時就可以考慮使用常用的正則優化手段進行優化,比如使用非貪婪模式,減少不必要的不定長量詞的使用等等。
其他幾個指令碼用處也很大,可以參考春哥的那個github頁面上的介紹。除了nginx-systemtap-toolkit外,春哥還有個stap++,是對systemtap的一個簡單擴充套件,功能也很多可以自行研究。
參考資料:
systemtap安裝:http://www.cnblogs.com/hazir/p/systemtap_introduction.html
nginx-systemtap-toolkit:https://github.com/openresty/nginx-systemtap-toolkit
stap++:https://github.com/openresty/stapxx
FlamgGraph tools:https://github.com/brendangregg/FlameGraph
二、核心除錯資訊
不用跟蹤核心態效能大概也不需要,不過保不齊會用到所以我也把核心除錯資訊搞上了。對於ubuntu這種發行版核心來說好處是官方已經提供了(URL:http://ddebs.ubuntu.com/pool/main/l/linux/),根據自己的核心(uname-a 查詢)挑選版本。 如我的是Linux ubuntu 3.13.0-32-generic那麼對應的就是:linux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb。
下載後用 dpkg -ilinux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb安裝。
三、Hello Systemtap!
上面這些完成以後可以使用命令:sudo stap -ve 'probe begin { log("hello Systemtap!")exit() }' 來測試是否安裝成功。如果成功的話會有類似下面的輸出:
四、nginx-systemtap-toolkit
進入正題,這個就是主要介紹的章亦春大神寫的systemtap nginx除錯的系列指令碼了(URL:Github地址),提供了活動請求的查詢、ngx_lua模組的當前lua堆疊檢視、pcre模式串/執行時間分析、C堆疊取樣等等炸裂功能。
首先介紹下C堆疊取樣這個指令碼,結合Brendan Gregg大神寫的FlameGraph tools(URL:https://github.com/brendangregg/FlameGraph),可以畫出功能實用、看著酷炫的火焰圖。如圖:
這個東西的原理就是在程式執行的時候每隔一定的時間對指定程序的C堆疊進行取樣,將當前各棧幀的函式名儲存起來。因為取樣時間是恆定的,所以最後的結果上如果一個函式佔用cpu時間越長,那麼得到的取樣次數也就越多,最後反映到火焰圖上的橫軸長度就越長。另外顏色深淺其實沒什麼含義,只是方便檢視。
使用方法:
1、首先確定編譯的程式碼要帶有除錯i資訊,以便除錯指令碼可以獲得具體的程式碼資訊。如nginx就要加上--with-debug開關。
2、其次要調優的程序已經啟動,並且獲得其pid,對於nginx這種多程序的程式,需要找到一個worker程序的pid,所以如果是開發環境調優的話,可以考慮使用單程序跑nginx。
3、命令sudo ./nginx-systemtap-toolkit/sample-bt -p 1147 -u -t 20 >trace.txt
其中-p 指定程序的pid
-u 追蹤使用者態的呼叫堆疊(也可以使用-k追蹤程式執行期間在核心態的堆疊)
-t 指令碼的執行時間,達到時間之後指令碼自動停止,將堆疊資訊輸出,單位為秒
啟動後會有類似的資訊:
WARNING: Tracing 1147 (/home/kawaru/nginx/sbin/nginx) in user-spaceonly...
提示已經開始跟蹤,這是可以用ab等等東西打點流量,等20秒之後會顯示:
WARNING: Time's up. Quitting now...(it may take a while)
這時候有可能需要多等一會,成功完成後會在trace.txt裡看到類似
一堆堆疊資訊。
4、製作火焰圖,這時就需要用到flame graph tools了,一共分為兩步:
一個是根據不同工具生成的堆疊資訊轉化為一個呼叫計數結果,因為我們用的是systemtap生成的,所以使用stackcollapse-stap.pl這個指令碼,命令如下:
./FlameGraph/stackcollapse-stap.pl ./trace.txt > trace.out
之後再使用flamegraph.pl生成最終的svg格式的火焰圖,命令:
./FlameGraph/flamegraph.pl ./trace.out > trace.svg
最後就可以看到瀏覽器裡開啟trace.svg,看到酷炫的火焰圖了:
上面介紹的是sample-bt這個指令碼,比較適用於cpu佔用較高時對低效程式碼的排查,如果cpu佔用不高,但執行的效率還是很低可以考慮是否是阻塞在io上,這時可以使用sample-bt-off-cpu這個指令碼,檢視io阻塞在哪段程式碼上,以便著手優化,使用方法差不多就不單獨介紹了。
另外一個比較實用的是ngx-pcre-stats 這個,可以追蹤nginx執行過程中跑pcre正則的效能,具體使用:
sudo ./ngx-pcre-stats -p 11276 --total-time-top --luajit20
-p 程序pid
--luajit20 根據系統裡用的是lua5.1還是luajit2.0分別使用--lua51或者--luajit20
--total-time-top 追蹤時的針對的專案,一共有四個除了total-time-top這個追蹤單個正則總計執行時間外,還有--exec-time-dist:檢視正則執行時間分佈,--worst-time-top,執行時間最差情況的十條正則;--data-len-dist正則匹配時匹配串的長度分佈。這四個專案每次執行時候選擇一個使用。
-t 跟蹤時間,單位為秒,不指定的話ctrl-c結束。
使用效果:
可以看出最差情況下第一條執行時間消耗比較多,這時就可以考慮使用常用的正則優化手段進行優化,比如使用非貪婪模式,減少不必要的不定長量詞的使用等等。
其他幾個指令碼用處也很大,可以參考春哥的那個github頁面上的介紹。除了nginx-systemtap-toolkit外,春哥還有個stap++,是對systemtap的一個簡單擴充套件,功能也很多可以自行研究。
參考資料:
systemtap安裝:http://www.cnblogs.com/hazir/p/systemtap_introduction.html
nginx-systemtap-toolkit:https://github.com/openresty/nginx-systemtap-toolkit
stap++:https://github.com/openresty/stapxx
FlamgGraph tools:https://github.com/brendangregg/FlameGraph