You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 19:30:35