示例说明
线上性能问题无法在本地复现时,需要的是运行中的生产进程自证。net/http/pprof 把分析端点挂到独立 mux——不与业务路由混用端口与路径,网络策略只放内网。CPU profile 是采样式的,开销约百分之一;锁与阻塞 profile 用比率参数控制精度与开销的平衡。
技术要点
- 独立 mux 与端口隔离诊断面
- CPU 采样开销仅百分之一量级
- 锁与阻塞按比率采样控开销
代码解读
setupProfiler 注册四种探针:索引页、CPU 采样、堆快照、goroutine 转储;server 在独立协程里监听,ErrServerClosed 是优雅关闭的正常返回。SetMutexProfileFraction 与 SetBlockProfileRate 分别按五分之一与两百纳秒粒度采样锁竞争与阻塞事件。
使用建议
诊断端口严禁暴露公网,配防火墙或仅绑回环地址。采样期间业务延迟有轻微抬升,避开峰值操作。go tool pprof 的火焰图与差异对比是核心排障手段。
代码示例
package main
import (
"fmt"
"log"
"net/http"
"net/http/pprof"
"runtime"
"time"
)
func busyWork() {
total := 0
for i := 0; i < 2_000_000; i++ {
total += i % 7
}
_ = total
}
func setupProfiler(addr string) *http.Server {
mux := http.NewServeMux()
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/heap", pprof.Handler("heap").ServeHTTP)
mux.HandleFunc("/debug/pprof/goroutine", pprof.Handler("goroutine").ServeHTTP)
server := &http.Server{Addr: addr, Handler: mux}
go func() {
log.Printf("pprof listening on %s", addr)
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Printf("pprof server error: %v", err)
}
}()
return server
}
func main() {
prof := setupProfiler("127.0.0.1:6060") // 仅内网可达,不暴露公网
defer prof.Close()
runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(200)
for i := 0; i < 3; i++ {
busyWork()
time.Sleep(100 * time.Millisecond)
}
// 使用方式:
// go tool pprof http://127.0.0.1:6060/debug/pprof/profile?seconds=10
// go tool pprof http://127.0.0.1:6060/debug/pprof/heap
fmt.Println("profile samples collected")
}