MongoDB连接持续增长问题排查(Node.js/Express环境)
问题:MongoDB连接持续增长,仅重启应用才断开
我的MongoDB数据库连接数一直在增长,只有重启应用时才会骤降(对应图表中的连接骤降节点)。我使用Node.js/Express将MongoDB作为用户数据库,想明确这个问题的成因。此前看到资料提到Node.js中不应手动关闭MongoDB连接。
已尝试的排查操作
- 关闭了统计并发连接的页面
- 检查过用户会话相关代码,未发现错误
相关代码片段
server.js 初始化连接
mongoose.connect(DBURI, { useNewUrlParser: true, useUnifiedTopology: true });
排行榜功能的连接代码
async function getRanking (callback) { await mongoClient.connect(uri, function(err, db) { if (err) throw err; var dbo = db.db("cluster0"); //Sort the result by name: var sort = { lastValue: -1 }; dbo.collection("users").find().sort(sort).toArray(function(err, result) { if (err) { console.log("Error ranking: " + err); throw err; } else { if (result.length >= 10) { for (let t = 0; t < 10; t++) { resultArr += ('|' + result[t].styledUsername.toString() + "!" + result[t].lastValue); } } else { for (let y = 0; y < result.length; y++) { resultArr += ('|' + result[y].styledUsername.toString() + "!" + result[y].lastValue); } } callback(complete(resultArr)); } }); }); }
其他位置的查询示例
User.findById(id, function(err, user) { done(err, user); });
问题成因与解决方案
核心原因
你在getRanking函数中每次调用都会通过mongoClient.connect新建连接,但未关闭连接:
- MongoDB原生驱动的
connect方法每次调用都会创建新连接,且这里没有执行db.close()释放连接,导致连接数持续累积。 - 你已经通过Mongoose建立了全局连接池,却又混用原生驱动创建独立连接,两种连接机制互不共享,进一步加剧了连接增长问题。
解决方案
方案1:统一使用Mongoose连接(推荐)
直接用Mongoose的User模型实现排行榜查询,复用全局连接池:
async function getRanking(callback) { try { // 直接使用Mongoose模型查询,自动复用连接池 const topUsers = await User.find() .sort({ lastValue: -1 }) .limit(10) .exec(); let resultArr = ''; topUsers.forEach(user => { resultArr += `|${user.styledUsername}!${user.lastValue}`; }); callback(complete(resultArr)); } catch (err) { console.log("Error ranking: " + err); throw err; } }
方案2:修复原生驱动的连接逻辑
如果一定要保留原生驱动调用,必须在查询完成(或出错)后关闭连接:
async function getRanking (callback) { await mongoClient.connect(uri, function(err, db) { if (err) throw err; var dbo = db.db("cluster0"); var sort = { lastValue: -1 }; dbo.collection("users").find().sort(sort).toArray(function(err, result) { // 无论成功还是失败,都要关闭连接 if (err) { console.log("Error ranking: " + err); db.close(); throw err; } let resultArr = ''; const limit = Math.min(result.length, 10); for (let t = 0; t < limit; t++) { resultArr += (`|${result[t].styledUsername}!${result[t].lastValue}`); } callback(complete(resultArr)); db.close(); // 查询完成后释放连接 }); }); }
额外提示
- Mongoose的
mongoose.connect只需调用一次,所有模型操作都会自动复用连接池中的连接,无需重复创建连接。 - 原生驱动也应只初始化一次连接,之后复用连接池,而不是每次查询都调用
connect。
内容的提问来源于stack exchange,提问作者Samuel Keller
相关产品推荐
相关产品推荐

