本文详解 mgo 驱动中因未合理配置连接池导致的连接泄漏问题,指出默认 `maxpoolsize=4096` 是并发请求下连接数失控的主因,并提供安全、高效的 session 复用与释放实践。
在使用 mgo(一个已归档但仍在部分遗留项目中使用的 Go MongoDB 驱动)构建高并发 REST API 时,开发者常采用“单 master session + 每请求 Copy()”的模式,意图复用连接并避免重复拨号。然而,这种做法若未配合正确的连接池配置,极易引发隐蔽而严重的连接泄漏——表现为 lsof -i :27017 显示大量处于 ESTABLISHED 状态的 TCP 连接持续累积,最终耗尽系统文件描述符(如达到 ulimit 1024 上限),导致服务不可用。
根本原因在于:mgo.Dial() 默认启用连接池,且 maxPoolSize 默认值为 4096。每次调用 session.Copy() 并非简单克隆轻量级句柄,而是可能从池中获取(或新建)底层网络连接;而 session.Close() 仅将连接归还至池中,而非真正关闭 TCP 连接。当并发请求数波动较大或存在长尾请求时,连接池会持续保有大量空闲连接以备后续复用——这本是性能优化设计,但在未限制池大小、又缺乏主动回收机制的场景下,便演变为资源泄漏。
✅ 正确解决方案如下: