Go (Golang) 应用监控:工具与库完全指南
监控是任何服务器应用运维中至关重要的一环。Go (Golang) 生态系统已开发出众多工具,用于实时跟踪性能、状态和错误。本文将深入探讨 Go 应用监控的关键库和方法,包括 Prometheus、expvar、pprof 和 OpenTelemetry。
为什么需要监控 Go 应用?
Go 应用常用于高负载微服务、API 网关和后台处理器。没有监控,您可能会错过:
- 内存和 goroutine 泄漏;
- 慢请求和锁竞争;
- 负载下的性能下降;
- 数据库和外部服务的连接错误。
1. Prometheus — 指标收集标准
Prometheus 是 Go 世界中指标收集的事实标准。官方客户端库 prometheus/client_golang 可以轻松以 Prometheus 格式导出指标。
安装
go get github.com/prometheus/client_golang/prometheusgo get github.com/prometheus/client_golang/prometheus/promhttp示例:请求计数器和时间直方图
package main
import ( "net/http" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")
var ( requestCount = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "endpoint"}, ) requestDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "Duration of HTTP requests in seconds", Buckets: prometheus.DefBuckets, }, []string{"method", "endpoint"}, ))
func init() { prometheus.MustRegister(requestCount, requestDuration)}
func middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() next.ServeHTTP(w, r) duration := time.Since(start).Seconds() requestCount.WithLabelValues(r.Method, r.URL.Path).Inc() requestDuration.WithLabelValues(r.Method, r.URL.Path).Observe(duration) })}
func main() { mux := http.NewServeMux() mux.Handle("/metrics", promhttp.Handler()) mux.Handle("/", middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }))) http.ListenAndServe(":8080", mux)}启动后,指标可通过 http://localhost:8080/metrics 访问。Prometheus 将配置从此端点进行采集。
2. expvar — 内置指标导出
Go 标准库提供了 expvar 包,用于发布应用状态变量。它不需要外部依赖。
使用示例
package main
import ( "expvar" "net/http")
var ( requests = expvar.NewInt("requests_total") errors = expvar.NewInt("errors_total"))
func handler(w http.ResponseWriter, r *http.Request) { requests.Add(1) // 模拟错误 if r.URL.Query().Get("error") == "1" { errors.Add(1) w.WriteHeader(http.StatusInternalServerError) return } w.Write([]byte("OK"))}
func main() { http.HandleFunc("/debug/vars", expvar.Handler().ServeHTTP) http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)}指标可通过路径 /debug/vars 以 JSON 格式访问。要与 Prometheus 集成,可以使用 <