Go (Golang) 应用监控:从指标到性能分析
Go (Golang) 是一种专为高负载服务器应用设计的语言。然而,即使是最高效的代码也可能出现故障、内存泄漏或不合理的高延迟。没有监控,您可能只有在收到愤怒用户的投诉后才知道问题。本文将介绍用于监控 Go 应用的关键库和工具:从指标收集到链路追踪和性能分析。
为什么要监控 Go 应用?
- 性能:跟踪响应时间、协程数量、CPU 和内存使用情况。
- 可靠性:监控错误、恐慌(panic)、重启次数。
- 扩展性:了解何时需要增加副本。
- 业务指标:请求数量、活跃用户、处理的数据量。
1. 内置包 expvar
最简单的方法是使用 expvar。它提供了一个包含基本指标的 HTTP 端点:协程数量、内存使用情况、运行时间。适合快速入门。
package main
import ( "expvar" "net/http")
var requestCount = expvar.NewInt("requests_total")
func handler(w http.ResponseWriter, r *http.Request) { requestCount.Add(1) w.Write([]byte("Hello, Go!"))}
func main() { http.HandleFunc("/", handler) // 指标可通过 /debug/vars 地址访问 http.ListenAndServe(":8080", nil)}启动应用并打开 http://localhost:8080/debug/vars — 您将看到包含指标的 JSON 数据。
2. Prometheus + prometheus/client_golang
Prometheus 是 Go 中指标收集的事实标准。prometheus/client_golang 库允许您注册自定义指标:计数器、直方图、摘要。
package main
import ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")
var ( httpRequests = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests.", }, []string{"method", "path"}, ))
func init() { prometheus.MustRegister(httpRequests)}
func handler(w http.ResponseWriter, r *http.Request) { httpRequests.WithLabelValues(r.Method, r.URL.Path).Inc() w.Write([]byte("OK"))}
func main() { http.HandleFunc("/", handler) http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil)}/metrics 端点以 Prometheus 可理解的格式提供数据。之后,您可以在 Grafana 中配置仪表板。
3. 使用 pprof 进行性能分析
net/http/pprof 包添加了用于性能分析的端点:CPU、内存、锁、协程。这是查找瓶颈的不可或缺的工具。
package main
import ( "net/http" _ "net/http/pprof" // 引入性能分析器)
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("性能分析已激活")) }) http.ListenAndServe(":6060", nil)}现在可以运行:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30这将收集 30 秒的 CPU 性能分析数据。您可以在交互模式下分析它,或导出为 SVG/PDF 格式。
4. OpenTelemetry — 链路追踪和指标
OpenTelemetry (OTel) 是现代可观测性标准。它统一了指标、日志和链路追踪。Go 有官方 SDK go.opentelemetry.io/otel。
package main
import ( "context" "log" "net/http" "go.opentelemetry.io