Go cron任务报goroutine stack exceeds 1000000000-byte limit错误如何排查
问题排查结果
核心问题1:无限制创建goroutine导致泄漏累积溢出
你每5分钟触发一次SendBookingMail,该函数会为数千个商户各调用一次StartCurlCommand,每次cmd.Start()执行成功后都会单独启动一个goroutine运行cmd.Wait(),且没有任何超时、并发管控逻辑:
- 只要curl请求因为网络波动、目标接口响应慢、链路故障等原因卡住,对应的goroutine就会永久挂起等待
cmd.Wait()返回 - 每5分钟就会新增数千个goroutine,积压到一定量级后,所有goroutine的栈总大小就会突破1GB限制,触发你遇到的报错
核心问题2:附属资源泄漏加速溢出
你给每个curl命令绑定了bytes.Buffer类型的out和stderr变量,只要curl进程不退出、goroutine不结束,这两个buffer占用的内存就不会被释放,会和积压的goroutine一起占用内存,进一步加快栈溢出的触发速度。
潜在递归触发点
如果你的SendBookingMail或者sendMailCron逻辑中,存在接口调用失败后重试时直接递归调用函数本身的逻辑,没有限制最大重试次数,也会形成无限递归,直接触发栈溢出,你可以重点检查错误重试相关的代码。
修复建议
- 给curl命令添加超时参数,比如在exec.Command的curl参数中添加
--max-time 30,强制超过30秒的请求直接退出,避免goroutine永久挂起 - 改用worker池控制并发数,比如固定启动10~20个worker,所有curl任务丢到channel中由worker消费,不要无限制创建goroutine
- 所有重试逻辑都要加上最大重试次数限制,禁止无限递归重试
- 建议替换exec调用curl的方案,直接用Go标准库
net/http包发送请求,减少额外进程创建开销,也更方便控制超时、错误处理逻辑
内容的提问来源于stack exchange,提问作者Amandeep kaur
相关产品推荐
相关产品推荐

