【问题标题】:How to maintain mongo client in NodeJS如何在 NodeJS 中维护 mongo 客户端
【发布时间】:2020-10-20 10:08:18
【问题描述】:

我正在尝试了解如何在节点应用程序中维护 mongo 客户端。我的第一个想法是在每次集合检索时创建一个客户端。像这样的:

const getCollection = (collectionName) => {
return MongoClient.connect(url, {useNewUrlParser: true, useUnifiedTopology: true})
    .then((client) => {
        const database = client.db(databaseName);
        return database.collection(collectionName);
    })
    .catch((err) => {
        console.log(err);
    });
};

然后使用返回的 promise 进行查询。像这样:

const executeFind = (collectionName, query, projection, skip, limit) => {
    return getCollection(collectionName)
        .then(collection => {
            return collection.find(query, {projection: projection})
                .skip(skip)
                .limit(limit)
                .toArray();
        })
        .catch((err) => {
            console.log(err);
        });
};

这种方法的问题在于,在运行应用程序时,与 mongo 的打开连接数会迅速增加,从而导致数据库操作出现问题并出现大量警报。

我考虑的连接增加的可能原因:

  • 大型池 - 我尝试将 maxPoolSize=5 添加到 URL。还将poolSize: 5 添加到options(MongoClient 的connect 函数的第二个参数。连接数仍然会激增。
  • 缺少连接关闭 - 我现在找不到文档,但我在某处读到连接由客户端本身管理,因此无需考虑 close() 对它们进行操作。但无论如何,我尝试在collection.find()返回结果后将代码重写为客户端close()。我收到Cannot use a session that has ended

除此之外,我没有任何其他想法要以一种在资源分配/运行方面有效的方式维护 mongo 客户端。我想听听这两个方面的答案:

  • 1。在这种方法中究竟可以做些什么来避免打开连接增加?
  • 2。维护mongo客户端的更通用/最佳/最佳实践方式是什么。

【问题讨论】:

    标签: node.js mongodb express connection


    【解决方案1】:
    • 检查下面的 sn-p 以获取 mongo db 池连接。

    MongoClient.connect(url, {
      poolSize: 10
      // other options can go here
    }, function(err, db) {
      global.mongodb = db;
    });
    • 为了处理连接,我们需要编写自定义代码,例如检查连接是否存在,如果不存在则创建新连接。

    【讨论】:

    • 也试过了。连接大小仍在增加。
    【解决方案2】:

    我可以部分回答我的问题。 我能够使用client.close() 解决连接增加问题。主要问题似乎是缺少承诺 await 所以 close() 导致意外行为(close() 有时发生在实际调用查询之前,并导致 session already closed 错误)。

    上述方法(每次调用打开和关闭连接)的问题是速度很慢。

    仍在寻找有关最佳维护客户端的一般答案。

    更新

    我终于能够找到不会打开大量连接并且也是最佳的解决方案。

    这里的技巧是在数据访问层(或数据库代码所在的任何地方)声明和调用异步函数,该函数将设置数据库对象。像这样的:

    let database;
    
    (async () => {
        const client = await MongoClient.connect(url, {poolSize: 150, useNewUrlParser: true, useUnifiedTopology: true});
        database = client.db(databaseName);
    })();
    

    然后在任何地方重用数据库对象,像这样:

    database.collection(collectionName).insertMany(documents);
    

    池和连接打开/关闭由client 处理。就最优性而言,它的速度更快(正如预期的那样)。不确定是否在 dao 中调用全局数据库或立即函数(虽然,由于文件是使用 require 导入的,因此不应多次调用)是最佳实践,但它确实可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多