pprof接口返回404是因为路由未被框架正确处理,gin需用r.get("/debug/pprof/pprof", gin.wraph(http.defaultservemux)),echo需用e.any("/debug/pprof/", echo.wraphandler(http.defaultservemux)),自定义mux须手动注册handler。

pprof 接口返回 404 怎么办
不是没启用,而是路由被拦截了。只要用了 Gin、Echo 或自定义 mux,http.ListenAndServe(":6060", nil) 就会失效——nil 只注册了 /debug/pprof/ 路径,但框架默认不透传。
必须显式挂载:
- Gin:用
r.GET("/debug/pprof/*pprof", gin.WrapH(http.DefaultServeMux)) - Echo:用
e.Any("/debug/pprof/*", echo.WrapHandler(http.DefaultServeMux)) - 生产环境更推荐 runtime/pprof 手动写文件,比如在收到
SIGUSR1时调用pprof.WriteHeapProfile(f),避免暴露 HTTP 接口
heap profile 看不出内存泄漏?
默认 /debug/pprof/heap 返回的是 inuse_space(当前存活对象),但泄漏往往藏在“净增长”里——比如缓存没清理、goroutine 持有句柄没释放。
正确做法是强制 GC 后对比两次快照:
- 先请求
curl -s "http://localhost:6060/debug/pprof/heap?gc=1" > heap1.pb.gz - 压测几分钟后再采
heap2.pb.gz - 运行
go tool pprof -base heap1.pb.gz heap2.pb.gz,看哪些函数的alloc_space增长最多
漏掉 ?gc=1 参数,看到的大多是待回收垃圾,不是真泄漏。
goroutine 数量暴涨却查不到?
/debug/pprof/goroutine 默认只显示状态为 running 或 runnable 的协程。大量泄漏的 goroutine 其实卡在 chan receive、select 或 semacquire 上,被过滤掉了。
加参数 ?debug=2 才能看到全部:
curl "http://localhost:6060/debug/pprof/goroutine?debug=2" > goroutines.txt- 搜索
chan receive或select,定位没关闭的 channel 或没设超时的 context - 配合
runtime.NumGoroutine()监控突增趋势,比单次采样更早发现问题
iostat 显示 %util 98% 但 r/s 很低,是磁盘瓶颈吗
是,而且大概率是大块同步 IO 卡住,比如日志刷盘、大文件 os.ReadFile 或数据库 fsync。
关键要交叉验证三件事:
-
iotop -o -P:确认是不是你的 Go 进程在持续写某个文件 -
lsof -p PID:看它打开了哪些文件,再df -h查对应挂载点是否满(尤其注意 XFS 下truncate -s 0不一定释放空间) -
cat /proc/PID/stack:输出里出现ext4_file_write_iter或overlayfs就坐实是文件系统层夯住,不是网络或 CPU 问题
这时候加 goroutine 也没用——os.ReadFile 是同步系统调用,阻塞在内核态,调度器根本插不上手。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











