Go 中的程序診斷

目錄


Introduction


Go 生態系統提供了大量 API 和工具來診斷 Go 程序中的邏輯和性能問題。此頁面總結了可用的工具,並幫助 Go 用戶針對他們的特定問題選擇正確的工具。

診斷解決方案可分爲以下幾組:

注意:某些診斷工具可能會相互干擾。例如,精確的 memory profiling 會扭曲 CPU profiles,而 goroutine blocking profiling 會影響 scheduler trace。隔離使用工具可獲得更精確的信息。

Profiling


Profiling 對於識別昂貴或經常調用的代碼段很有用。Go runtime 以 pprof 可視化工具所期望的格式提供 profiling data。在測試期間可以通過 go test 或 net/http/pprof 包提供的 endpoints 收集 profiling data。用戶需要收集 profiling data 並使用 pprof 工具來過濾和可視化頂部代碼路徑。

runtime/pprof 包提供的預定義 profiles:

我可以使用其他哪些 profilers 來介紹 Go 程序?

在 Linux 上,perf tools 可用於分析 Go 程序。Perf 可以 profile 和展開 cgo/SWIG 代碼和內核,因此深入瞭解 native / 內核性能瓶頸非常有用。在 macOS 上, Instruments 套件可以用來 profile Go 程序。

我可以 profile 我的生產環境的服務嗎?

是的。在生產環境中對程序進行 profile 是安全的,但啓用某些 profiles(例如:CPU profile)會增加消耗。您應該會看到性能降級。在生產中打開探測器之前,可以通過測量 profiler 的開銷來估計性能損失。

您可能希望定期分析您的生產服務。特別是在具有單進程多副本的系統中,定期選擇隨機副本是安全的選擇。選擇一個生產服務, 每隔 Y 秒 profile X 秒並保存結果以進行可視化和分析; 然後定期重複。可以 手動 / 自動 檢查結果以發現問題。profiles 收集可能會相互干擾,因此建議一次只收集一個 profile。

可視化分析數據的最佳方法是什麼?

Go tools 使用 go tool pprof 提供文本,圖形和 callgrind 可視化的 profile data。閱讀 Profiling Go programs 以查看它們的實際使用。

pprof-text.png

文本方式查看最大的消耗的調用

pprof-dot.png

圖片方式可視化最大的消耗的調用

Weblist 視圖在 HTML 頁面中逐行顯示源代碼最大消耗的部分。在以下示例中,530ms 用於 runtime.concatstrings,每行的消耗顯示在列表中。

pprof-weblist.png

weblist 方式可視化最大的消耗的調用

另一種可視化輪廓數據的方法是火焰圖。火焰圖允許您在特定的祖先路徑中移動,因此您可以放大 / 縮小特定的代碼段。upstream pprof 支持火焰圖。

flame.png

火焰圖方式可視化以發現最昂貴的代碼路徑

我是否僅限於內置 profiles?

除了 runtime 提供的工具之外,Go 用戶還可以通過 pprof.Profile 創建自定義 profiles,並使用現有工具對其進行檢查。

我可以在不同的路徑和端口上提供 profiler handlers(/debug/pprof/…) 嗎?

是的。默認情況下, net/http/pprof 包將其 handlers 註冊到默認的 mux,但您也可以使用從包中導出的 handler net/http/pprof 註冊它們。

例如,以下示例將在 7777 端口 / custom_debug_path/profile 上提供 pprof.Profile handler:

package main

import (
 "log"
 "net/http"
 "net/http/pprof"
)

func main() {
 mux := http.NewServeMux()
 mux.HandleFunc("/custom_debug_path/profile", pprof.Profile)
 log.Fatal(http.ListenAndServe(":7777", mux))
}

Tracing


Tracing 是一種檢測代碼的方法,用於分析一系列調用的生命週期中的延遲。Go 提供 golang.org/x/net/trace 包作爲每個 Go 節點的最小 tracing backend,並提供一個帶有簡單儀表板的最小檢測庫。Go 還提供了一個執行跟蹤器來跟蹤時間間隔內的 runtime events。

Tracing 使我們能夠:

在單機系統中,從程序的構成模塊收集診斷數據相對容易。所有模塊都位於一個進程中,並共享公共資源以報告日誌,錯誤和其他診斷信息。一旦您的系統超出單個進程並開始變爲分佈式,跟蹤從前端 Web 服務器到其所有後端的調用,直到將響應返回給用戶,將變得更加困難。這就是分佈式 tracing 在檢測和分析生產系統方面發揮重要作用的地方。

分佈式 tracing 是一種檢測代碼的方法,用於分析用戶請求在整個生命週期中的延遲。當系統分佈式化,並且傳統的分析和調試工具無法 scale 時,您可能希望使用分佈式 tracing 工具來分析用戶請求和 RPC 的性能。

分佈式 tracing 使我們能夠:

GO 生態系統爲每個跟蹤系統提供了不同的分佈式跟蹤庫和後端無關的跟蹤庫。

有沒有辦法自動攔截每個函數調用並創建 tracing ?

Go 沒有提供自動攔截每個函數調用和創建 trace spans 的方法。您需要手動檢測代碼以創建,結束和註釋 spans。

我應該如何在 Go 庫中傳播 trace headers ?

您可以在 context.Context 傳播 trace 標識符和標記。目前行業中還沒有 trace key 的規範和 trace headers 的通用表示。每個 tracing 提供程序都負責在其 Go 庫中提供傳播工具。

標準庫或 runtime 中的其他低級事件可以包含在 trace 中嗎?

標準庫和 runtime 試圖公開幾個額外的 API 來通知低級內部事件。例如, httptrace.ClientTrace 提供 API 以跟蹤傳出請求生命週期中的低級事件。目前正在努力從 runtime execution tracer 中檢索低級運行時事件,並允許用戶定義和記錄其用戶事件。

Debugging


Debugging 是識別程序錯誤行爲的過程。調試器允許我們理解程序的執行流程和當前狀態。有幾種調試方式;本節只關注將調試器 attach 到程序和 core dump 調試。

GO 用戶主要使用以下調試器:

調試器與 Go 程序的兼容性如何?

gc 編譯器執行優化,例如函數內聯和變量註冊。這些優化有時會使調試器調試更困難。目前正在努力提高優化後的二進制文件的 DWARF 信息的質量。在這些改進可用之前,我們建議在構建正在調試的代碼時禁用優化。以下命令構建一個沒有編譯器優化的包:

$ go build -gcflags=all="-N -l"

作爲改進工作的一部分,Go 1.10 引入了一個新的編譯器 flag -dwarflocationlists。該標誌使編譯器添加位置列表,以幫助調試器使用優化後的二進制文件。以下命令構建使用優化但包含 DWARF 位置列表的包:

$ go build -gcflags="-dwarflocationlists=true"

推薦的用戶界面調試器是什麼?

儘管 delve 和 gdb 都提供了 CLI,但大多數集成編輯器和 IDE 都提供了特定於調試的用戶界面。

是否可以使用 Go 程序進行事後調試?

core dump 文件是包含正在運行的進程及其進程狀態的 memory dump 文件。它主要用於程序的事後調試,並瞭解它仍在程序運行時的狀態。這兩種情況使 core dump 的調試成爲一種良好的診斷工具,可用於事後分析和分析生產服務。可以從 Go 程序獲取 core 文件,並使用 delve 或 gdb 進行調試,請參閱 core dump debugging 頁面以獲取分步指南。

Runtime statistics and events


runtime 爲用戶提供內部事件的統計信息和報告,以便在 runtime 級別診斷性能和利用率問題。

用戶可以監控這些統計數據,以更好地瞭解 Go 程序的整體運行狀況和性能。一些經常監控的統計數據和狀態:

Execution tracer


Go 附帶了一個 runtime execution tracer,用於捕獲各種運行時事件。調度,系統調用,垃圾收集,堆大小和其他由 runtime 收集的事件,並可通過 go tool trace 進行可視化。Execution tracer 是一種檢測延遲和利用率問題的工具。您可以檢查 CPU 的使用情況,以及當網絡或系統調用成爲 goroutines 搶佔的原因。

Tracer 使我們能夠:

但是,識別熱點(如分析內存過多或 CPU 使用率的原因)並不是很好用。首先使用 profiling tools 來解決它們。

tracer-lock.png

以上,go tool trace 可視化顯示執行開始正常,然後它變得順序化。它表明可能存在共享資源的鎖競爭導致的瓶頸。

請參閱 go tool trace 以收集和分析 runtime traces。

GODEBUG


如果相應地設置了 GODEBUG 環境變量,Runtime 也會發出事件和信息。

GODEBUG 環境變量可用於禁用標準庫和 runtime 中 instruction set extensions 的使用。

本文轉自 Go 生態,由 cyningsun 翻譯

原文地址爲:https://www.cyningsun.com/07-21-2019/go-diagnostics-cn.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Iw62OlQ7nhpJiLVyEV0dKQ