Express/Next项目Mongoose连接MongoDB Atlas数量过多问题咨询
问题根因总结
你当前连接数超标的核心原因有两个:
- 常规mongoose连接和MongoStore会话存储各自创建了独立连接池,连接数直接翻倍
- 未配置连接超时规则和进程退出时的连接回收逻辑,旧连接长期占用资源不释放
问题1:生产环境推荐的mongoose连接参数
推荐配置如下核心参数,同时将MongoStore改为复用现有mongoose连接,避免重复创建连接池:
优化后的mongoose连接代码
mongoose.connect(process.env.INRMONGODB, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false, useCreateIndex: true, // 生产环境核心配置 poolSize: 3, // 总连接数=进程数*poolSize,建议控制在Atlas连接阈值的70%以内 serverSelectionTimeoutMS: 5000, // 服务器选择超时时间,避免长时间挂起 connectTimeoutMS: 5000, // 单连接建立超时时间 socketTimeoutMS: 30000, // socket空闲30秒自动释放 family: 4 // 强制使用IPv4,避免Atlas解析异常 }, (err) => { if (err) { console.log(err, "MONGODB CONNECTION ERROR"); return false; } console.log("Mongoose Is Connected"); } );
优化后的会话存储代码(复用连接)
app.use(session({ secret: process.env.SESSION_SECRET, saveUninitialized: false, resave: false, rolling: false, name: process.env.COOKIENAME, cookie: sessionCookieOptions, store: new MongoStore({ // 删除原有uri参数,复用现有mongoose连接,避免额外创建连接池 mongooseConnection: mongoose.connection, ttl: 2000, autoRemove: 'interval', autoRemoveInterval: 20, hash: { salt: process.env.SALTSECRET, algorithm: 'sha1' } }) }));
问题2:是否需要在进程收到信号时主动关闭数据库连接
需要。SIGTERM、SIGINT这类可捕获的退出信号,监听后主动调用mongoose.disconnect()可以正常释放连接池所有连接,避免服务端等待超时才回收。SIGKILL信号无法被捕获,无需处理。
连接回收代码示例
// 监听退出信号主动释放连接 const closeConnection = async () => { console.log('进程退出,正在关闭数据库连接'); await mongoose.disconnect(); process.exit(0); } process.on('SIGTERM', closeConnection); process.on('SIGINT', closeConnection);
问题3:5个进程连接数达70+且随用户操作波动的原因
主要有三点:
- 原有逻辑每个进程创建2个独立连接池,默认单池大小为5的情况下,5个进程基础连接就有525=50个,加上Atlas自带的3-5个内部监控连接,基础值已经很高
- 未配置
socketTimeoutMS时,空闲连接不会自动释放,用户并发请求高时连接池会临时创建额外连接处理请求,用完后长期占用资源 - 你观测到的连接数突然下降是MongoDB服务端达到默认的空闲连接超时阈值后,才批量回收僵死连接导致的
问题4:服务重启连接数累计增加的情况是否存在
存在。进程退出时没有主动关闭连接,MongoDB服务端感知不到连接已经失效,会一直保留这些连接直到服务端默认的空闲超时(通常为30分钟)才会回收,每次重启就新增一批连接,累计后就会触发阈值。添加上述的信号监听主动回收连接逻辑后即可解决该问题。
内容的提问来源于stack exchange,提问作者Vitthal Kulkarni
相关产品推荐
相关产品推荐

