pprof 连不上因默认监听 localhost,需显式绑定 0.0.0.0:6060 并检查网络策略;查全部 goroutine 必加 ?debug=2;定位泄漏靠对比快照中 created by 行;命令行比 Web UI 更适合深度分析。

pprof 启动后为啥 go tool pprof 连不上?
默认 net/http/pprof 只监听 localhost:6060,本地命令行能连上,但容器里跑、远程调试或非 127.0.0.1 绑定时就会报 connection refused 或超时。
- 启动服务时显式绑定到
0.0.0.0:6060:用http.ListenAndServe("0.0.0.0:6060", nil),别只写":6060"(Go 1.19+ 默认仍为 localhost) - 确认端口没被防火墙/iptables/Docker network 阻断;K8s Pod 中还要检查 Service 是否暴露了该端口
-
curl http://localhost:6060/debug/pprof/能返回 HTML 列表,才是 pprof HTTP 接口真正就绪
怎么快速抓取 goroutine 的实时快照?
不是所有 goroutine 都在运行,/debug/pprof/goroutine 默认只返回正在执行的(即 running 状态),想看全部得加 ?debug=2 参数——这是最容易漏掉的关键开关。
- 获取全部 goroutine 堆栈(含阻塞、休眠、等待中):
curl 'http://localhost:6060/debug/pprof/goroutine?debug=2' > goroutines.txt - 直接用 pprof 工具交互分析:
go tool pprof http://localhost:6060/debug/pprof/goroutine?debug=2 - 在 pprof CLI 里输入
top看数量最多的 goroutine 类型,list main.查看某函数相关协程调用链
goroutine 泄漏怎么定位?
泄漏本质是 goroutine 启动后永远卡住不退出,常见于 channel 读写不匹配、WaitGroup 忘记 Done()、timer 不 stop、或 select 没 default 分支导致永久阻塞。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 对比两次快照差异:分别用
?debug=2抓取间隔几十秒的两个文件,用diff -u a.txt b.txt | grep '^+' | grep 'created by'看新增的协程来源 - 重点关注
created by行,它指向启动该 goroutine 的函数和行号,比堆栈顶部更准 - 如果大量 goroutine 停在
runtime.gopark或chan receive/semacquire,大概率是 channel 或 mutex 使用不当
Web UI 和命令行哪个更适合查 goroutine?
Web UI(http://localhost:6060/debug/pprof/goroutine?debug=2)适合快速浏览,但无法搜索、过滤或比对;命令行 go tool pprof 支持正则匹配、按函数聚合、导出 SVG,更适合深度排查。
立即学习“go语言免费学习笔记(深入)”;
- 快速筛查某业务模块:在 pprof CLI 输入
top -cum -regex 'myapp/handler|api.' - 导出火焰图看 goroutine 分布:
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/goroutine?debug=2 - 注意:Web 页面默认是
debug=1(只显示 runnable + running),必须手动改 URL 加?debug=2才全量
真正麻烦的不是看不到 goroutine,而是看到几百个都停在同一个 channel receive 上却不确定是谁没关 channel、谁忘了 close、谁在循环里反复启新 goroutine 却没做退出控制——这时候得结合代码路径和 created by 行交叉验证。

















