实战:排查 Go 语言中 goroutine 泄露导致的进程 RSS 持续上涨
作者:RiverSoul
时间:2026-07-03
浏览:0
goroutine泄漏导致RSS上涨并非栈内存占用,而是钉住了channel、timer等资源。排查需关注goroutine数量趋势而非单次值,用pprof快照对比新增堆栈,警惕chanreceive/select长阻塞。Go1.24+的goroutineleak端点可标记不可达阻塞。泄漏常藏于下游客户端代码中。
goroutine 泄漏确实会导致 RSS 持续上涨,但问题根源不在每个 goroutine 本身占多少内存——默认栈也就 2KB 左右——而是它钉住了背后的 channel、timer、HTTP connection、闭包捕获的大对象等资源。说白了,这些被“钉死”的资源才是真正吃 RSS 的主力。如果发现 heap profile 显示内存稳定,RSS 却一路走高,八成就是这个原因。

runtime.NumGoroutine() 涨了,但不确定是不是真泄漏
数字变大不等于泄漏,核心得看趋势和上下文:
- 刚启动 HTTP 服务时
runtime.NumGoroutine()跳到 100+ 是正常的,pprof、healthz、日志 flusher 都在初始化阶段,这是预期行为。 - 真正需要盯的是三种情形:单次请求返回后数字没回落;压测结束 30 秒后仍比空闲态高出一大截;稳定运行几小时呈单调上升(比如从 60 涨到 240 再到 960)。
- 建议在关键路径打三处日志:
log.Printf("goroutines@idle: %d", runtime.NumGoroutine())、@start、@done,别只采一次样就下结论。
/debug/pprof/goroutine?debug=2 显示大量 chan receive/select
这是泄漏最典型的 pprof 表现,但光看到“卡住”还不够,得确认是不是新长出来的:
- 先抓 baseline 快照(空闲态),压测或跑一段时间后再抓一次,用
diff工具比对新增 goroutine 的堆栈。 - 重点关注阻塞时长字段:出现
432000s(5 天)、1209600s(14 天)这种量级,基本可以断定是泄漏,不是慢操作。 - 常见高危模式:
nil chan上收发、无缓冲chan单向操作、有缓冲chan写满未消费、select所有case不可达且无default。 - 如果堆栈集中在
net/http.readLoop或golang.org/x/crypto/ssh,优先检查服务端是否设置了ReadTimeout/IdleTimeout。
goleak.VerifyNone 在测试里没报,但线上还是涨
这倒不是 goleak 本身不好使,而是它的检测逻辑和线上场景匹配不上:
goleak.VerifyNone(t)只捕获测试函数退出时“还活着”的 goroutine;如果泄漏的 goroutine 在t结束前就因超时或 channel 关闭退出了,它就看不见。- 正确做法是确保待测逻辑完整执行完再验证,比如加
time.Sleep(10ms)或等done chan关闭;更稳妥的是用goleak.VerifyTestMain(m)包裹整个TestMain。 - 注意误报:第三方库(如
http.Server、time.AfterFunc)启动的 goroutine 需显式用goleak.IgnoreTopFunction()过滤。
Go 1.24+ 的 /debug/pprof/goroutineleak 端点怎么用
这算是目前最接近“自动识别泄漏”的手段了,但得配好环境、等 GC 跑完:
- 启动时加环境变量:
GODEBUG=goleak=1(Go 1.24+)或GOROUTINELEAK=1(gotip 实验版)。 - 首次访问
/debug/pprof/goroutineleak?debug=1前,手动触发一次runtime.GC(),否则可能为空。 - 返回堆栈中带
_Gleaked状态标记的 goroutine,就是被 GC 层确认“不可达且阻塞”的泄漏项。 - 需要注意的是,它不抓死循环或无限重试类泄漏,只抓卡在
chan、select、semacquire等同步原语上、且无退出路径的 goroutine。
话说回来,最容易被忽略的一点是:泄漏的 goroutine 往往不直接出现在业务 handler 里,而是藏在下游 client、ticker、ssh.Dial、甚至 http.Response.Body 未关闭导致的 persistConn 持有中——排查的时候别只盯着自己写的 go func()。
作者最新文章
微软推出Project Zenith:面向Windows 11开发者的AI硬件加速方案
2026-09-08 18:15
打破流量垄断,让平台经济释放普惠红利
2026-09-08 18:07
Arm AGI CPU详解:136核Neoverse V3,3nm双芯粒架构与AI数据中心部署
2026-09-08 17:18
Windows安装Docker教程:启用WSL2并运行第一个容器验证
2026-09-04 09:26
PDF转Word操作指南:在线与本地转换方法及格式检查
2026-09-03 16:03
热门文章
更多
精品专题
更多
Mac软件
更多
WINDOWS
更多


































