← 中文资源

简体中文版本

Pprof 运行时性能分析端点

在内网端口暴露 Go 运行时分析端点:CPU 采样、堆快照、goroutine 转储随时可取,锁与阻塞 profiling 按比率开启。

阅读英文原文

示例说明

线上性能问题无法在本地复现时,需要的是运行中的生产进程自证。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")
}