pprof不是“开了就灵”的开关,而是需明确目标、独立端口暴露(如127.0.0.1:6060)、按问题选profile(cpu用/profile,内存泄漏用/heap?gc=1,goroutine暴涨用/goroutine?debug=2)、分析时必带原始二进制文件。

Go 服务性能问题不能靠猜——pprof 不是“开了就灵”的开关,而是需要对准目标、控制采样、匹配分析路径的诊断仪器。
如何用 net/http/pprof 安全暴露线上服务的性能端点
直接在主 HTTP mux 上挂 _ "net/http/pprof" 是常见错误:它会把 /debug/pprof/ 暴露在业务端口下,可能被中间件拦截、日志泄露,甚至被未授权访问扫出 goroutine 栈或内存快照。
- 必须启动独立监听地址,例如
http.ListenAndServe("127.0.0.1:6060", nil),禁用外部访问 - 若需公网访问(如调试预发),务必加反向代理鉴权或 IP 白名单,不可仅靠路径隐藏
- 导入语句只需
_ "net/http/pprof",它会自动注册所有/debug/pprof/*路由,无需手动Handle - 访问
http://localhost:6060/debug/pprof/可列出全部 profile 类型;点击profile默认采集 30 秒 CPU 数据,heap返回当前堆分配总量
go tool pprof 分析时该选哪个 URL 或文件
选错 profile 类型,等于拿温度计测血压——数据真实,但完全不反映你要的问题。
- CPU 占用高:用
http://host:6060/debug/pprof/profile?seconds=60(采样正在运行的 goroutine 栈帧) - 内存持续上涨:先取
/debug/pprof/heap?gc=1(GC 后存活对象),再比对多次快照;避免只看默认/heap(含已分配但已回收的对象) - goroutine 数量暴涨:直击
/debug/pprof/goroutine?debug=2,文本格式可读性强,能一眼识别卡在chan recv、select或锁上的 goroutine - 阻塞或锁竞争:必须提前在代码中调用
runtime.SetBlockProfileRate(1)和runtime.SetMutexProfileFraction(1),否则/block和/mutex返回空
为什么火焰图里全是 runtime.goexit 或十六进制地址
这不是 pprof 坏了,是你没给它“认人”的线索——缺少符号表(symbol table),即编译时剥离了调试信息。
- 确保二进制是用默认方式构建的,不要加
-ldflags="-s -w"(它们会删掉函数名和行号) - 分析时必须使用**原始编译出的二进制文件**:例如
go tool pprof ./myapp cpu.prof,不能只传 profile 文件 - 如果用 Docker 部署,确保容器内保留二进制(或挂载宿主机的原文件),别用 alpine 镜像直接跑 stripped 二进制
- 交叉编译时注意 GOOS/GOARCH 匹配,否则符号解析失败,也会退化为地址
真正卡住人的从来不是工具不会用,而是采样时机不对、profile 类型错配、或分析时丢了二进制本身——这三处漏掉任何一环,pprof 给你的就是一张漂亮但无用的地图。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











