推薦一款不錯的 Go 持續分析工具
年前土撥鼠分享了一篇鳥窩老師寫的 Pyroscope: 簡單易用的持續分析 (Continuous profiling) 服務器。今天土撥鼠帶來一篇官方更生動的實例文章。本篇文章翻譯自 Continuous Profiling for Go Applications[1]。翻譯不當之處煩請指出。
源碼地址:https://github.com/pyroscope-io/pyroscope/tree/main/examples/golang-push。
使用 Pyroscope — 一個開源的持續分析平臺
使用 Pyroscope 分析 Golang Rideshare 應用程序
在這個例子中,展示了一個基本的用例,即如何使用 Pyroscope[2](一個開源的分析庫)來加速 Golang 應用程序使用持續分析。
我們模擬了一家 "拼車" 公司,該公司在 main.go
中有三個路徑endpoint
(這裏 endpoint 翻譯參考 阮一峯 [3] 寫的 RESTful API 設計指南 [4] 中的翻譯):
-
/bike
:調用OrderBike(searchRadius)
函數來訂購一輛自行車 -
/car
:調用OrderCar(searchRadius)
函數訂購一輛汽車 -
/scooter
:調用OrderScooter(searchRadius)
函數來訂購一輛踏板車
我還模擬在 3 個不同的區域運行 3 個不同的服務器(通過 docker-compose.yml[5])
-
美國東部 - 1
-
美國西部 - 1
-
歐洲西部 - 1
Pyroscope 最有用的功能之一是能夠以對你有意義的方式標記數據。在本例中,我們有兩個自然劃分,因此我們 "標記" 我們的數據來表示它們:
-
區域
region
:靜態地標記運行代碼的服務器的區域 -
車輛
vehicle
:動態地標記路徑(類似於標記控制器軌道的方式)
對區域進行靜態標記
標記靜態內容(如region
)可以在 main()
函數的初始化代碼中完成:
pyroscope.Start(pyroscope.Config{
ApplicationName: "ride-sharing-app",
ServerAddress: serverAddress,
Logger: pyroscope.StandardLogger,
Tags: map[string]string{"region": os.Getenv("REGION")},
})
在函數內進行動態標記
像我們爲車輛vehicle
標記的那樣,可以在我們的實用函數FindNearestVehicle()
中使用pyroscope.TagWrapper()
來動態地標記一些東西。
func FindNearestVehicle(search_radius int64, vehicle string) {
pyroscope.TagWrapper(context.Background(), pyroscope.Labels("vehicle", vehicle), func(ctx context.Context) {
// 模擬找到一輛車 Mock "doing work" to find a vehicle
var i int64 = 0
start_time := time.Now().Unix()
for (time.Now().Unix() - start_time) < search_radius {
i++
}
})
}
這塊的功能是:
-
它添加了標籤
pyroscope.Labels("vehicle", vehicle)
-
它執行
FindNearestVehicle()
函數 -
在塊結束之前,它(在幕後)從應用程序中移除了
pyroscope.Labels("vehicle", vehicle)
,因爲該塊已經執行完成。
使用火焰圖顯示性能瓶頸
在分析應用程序的配置文件輸出時,第一步是注意最大的節點,即應用程序消耗最多資源的地方。在本例中,它恰好是 OrderCar()
函數。
使用 Pyroscope 包的好處是,現在我們可以進一步研究爲什麼OrderCar()
函數會有問題。標記region
和vehicle
使我們可以對兩個很好的假設進行測試:
-
/car
路徑的代碼有問題 -
我們的某個地區
region
有問題
要對此進行分析,我們可以從 "Select Tag" 下拉列表中選擇一個或多個標籤:
使用標籤縮小性能問題的範圍
知道 OrderCar()
函數存在問題後,我們會自動選擇該標籤。然後,在檢查多個region
標籤後,通過查看時間線可以清楚地看出 us-west-1
區域存在問題,它在高 CPU 時間和低 CPU 時間之間交替。
我們還可以看到,mutexLock()
函數消耗了近 70% 的 CPU 資源。
比較兩個時間段
使用 Pyroscope 的 "比較視圖 - comparison view",我們可以從時間軸中選擇兩個不同的時間範圍來比較生成的火焰圖。左側時間軸上的粉紅色部分生成左側火焰圖,右側的藍色部分表示右側火焰圖。
當我們選擇低 CPU 使用率週期和高 CPU 使用率週期時,我們可以看到 mutexLock()
函數中存在不同的行爲 ,其中它在低 CPU 時間佔用 33% 的 CPU,在高 CPU 時間佔用 71% 的 CPU。
可視化兩個火焰圖之間約有 112% 的性能差異
雖然在這種情況下,差異是很顯而易見的,但有時兩個火焰圖之間的差異最好通過相互疊加才能更好地可視化。無需更改任何參數,我們只需選擇 **(Diff View) 差異視圖選項卡 **,即可查看顏色編碼的差異火焰圖中表示的差異。
更多用例
無論你是從事副業的開發人員,還是一個想知道 "如何加快我的 Go 應用程序" 的 DevOps 工程師,Pyroscope 都有許多用例,可以輕鬆瞭解如何分析您的應用程序。下面是一些示例:
-
標記 Kubernetes 屬性
-
標記控制器
-
標記區域
-
標記隊列中的任務
-
標記提交
-
標記生產環境
-
標記測試套件的不同部分
未來路線圖
如果你想嘗試此示例,並查看如何將其調整到您的 Go 應用程序,請單擊 github 上此示例 [6] 的鏈接。持續分析已成爲監視和調試性能問題(可以說是可觀察性的第四個支柱)的日益流行的工具。
如果您對 Pyroscope[7] 如何改進有想法,請隨時在 GitHub 頁面上提交你的問題!感謝您的閱讀。
參考資料
[1]
Continuous Profiling for Go Applications: https://betterprogramming.pub/continuous-profiling-go-applications-8cdbdfdfc5ab
[2]
Pyroscope: https://github.com/pyroscope-io/pyroscope
[3]
阮一峯: https://www.ruanyifeng.com/
[4]
RESTful API 設計指南: https://www.ruanyifeng.com/blog/2014/05/restful_api.html
[5]
docker-compose.yml: https://github.com/pyroscope-io/pyroscope/blob/main/examples/golang-push/rideshare/docker-compose.yml
[6]
github 上此示例: https://github.com/pyroscope-io/pyroscope/blob/main/examples/golang-push/README.md
[7]
Pyroscope: https://pyroscope.io/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/GrDFbTjXvC_uyXynceOpzw