Hasty Briefsbeta

双语

Finding and Fixing a 50k Goroutine Leak That Nearly Killed Production

4 months ago
  • #goroutine-leak
  • #production-incident
  • #debugging
  • 某生产环境的API服务出现严重goroutine泄漏问题,六周内从1,200个goroutine激增至50,847个,导致内存占用飙升至47GB,接口响应时间延迟达32秒。
  • 泄漏根源在于WebSocket通知系统中存在三个关键缺陷:未调用context的cancel()方法、未停止定时器ticker、未关闭通信通道channel。
  • Uber的LeakProf工具在定位泄漏过程中发挥关键作用,发现已断开的WebSocket连接对应的goroutine未被清理。
  • 修复方案包括:规范资源回收流程——执行context的cancel()、停止ticker、关闭channel,并建立连接监测机制及时清理失效连接。
  • 采用分阶段恢复策略:先实施紧急止血措施,再运行清理脚本消除现存泄漏,最后部署新型监控防止复发。
  • 新增Prometheus监控指标,包括goroutine数量、WebSocket订阅数、活跃连接数等核心指标告警体系。
  • 强化测试方案:增加泄漏检测测试、针对泄漏的负载测试、支持goroutine追踪的基准测试。
  • 核心经验教训:必须明确goroutine退出机制、规范资源回收流程、监控goroutine数量变化、开展泄漏专项测试。
  • 该故障导致性能劣化、客户投诉、人力成本、额外AWS支出及商誉损失等多维损失。
  • 现行预防机制包括:提交前钩子检测遗漏的ticker.Stop()调用,测试中强制使用goleak进行泄漏检测。