【问题标题】:Keeping open a MongoDB database connection保持打开 MongoDB 数据库连接
【发布时间】:2013-09-10 03:32:27
【问题描述】:

在许多使用 MongoDB 的介绍性示例中,您会看到如下代码:

var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:port/adatabase", function(err, db)
{
    /* Some operation... CRUD, etc. */
    db.close();
});

如果 MongoDB 与任何其他数据库系统一样,openclose 操作通常在时间上很昂贵。

所以,我的问题是:是否可以简单地执行一次MongoClient.connect("...,将返回的db 值分配给某个模块全局,让模块中的各种函数执行各种与数据库相关的工作(将文档插入集合,更新文档等)当它们被应用程序的其他部分调用时(从而重新使用该db值),然后,当应用程序完成时,才执行close .

换句话说,openclose 只执行一次 - 不是每次您需要去执行一些与数据库相关的操作时。并且您继续重复使用在初始open\connect 期间返回的db 对象,只是在最后使用close 处理它,当您实际完成所有与数据库相关的工作时。

显然,由于所有 I/O 都是异步的,因此在 close 之前,您需要确保在发出 close 之前完成最后一个数据库操作。看起来这应该没问题,但我想仔细检查以防万一我错过了一些东西,因为我是 MongoDB 的新手。谢谢!

【问题讨论】:

  • 也可以查看this,可能对你有帮助
  • 有趣.... 是的,有帮助;非常感谢!

标签: node.js mongodb


【解决方案1】:

是的,这是很好的典型行为。启动您的应用程序,连接到数据库,长时间对数据库执行操作,如果连接意外终止,则可能重新连接,然后永远不要关闭连接(只需依赖进程终止时发生的自动关闭) .

【讨论】:

  • 此外,默认情况下,使用 node-mongodb-native 可以获得 5 个池连接。查看poolSize 上的文档。
  • 非常感谢您证实了我的怀疑,彼得 - 非常感谢!
  • 我遵循了解决方案stackoverflow.com/a/24634454/3994271,它的作用与此答案中提到的相同。但是,如果连接意外断开,我们如何自动重新连接?
  • 这是一个非常有帮助的答案,但是如果它提供了一种在连接断开时保持连接状态的方法,它可能会更有帮助。
  • 查看下面@MihirPatel 的回答,了解如何让您的 mongo 客户端轻松重新连接。
【解决方案2】:

mongodb版本^3.1.8

将连接初始化为承诺:

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://...'
const client = new MongoClient(uri)
const connection = client.connect() // initialized connection

然后在您希望对数据库执行操作时调用连接:

    // if I want to insert into the database...
    const connect = connection
    connect.then(() => {
        const doc = { id: 3 }
        const db = client.db('database_name')
        const coll = db.collection('collection_name')
        coll.insertOne(doc, (err, result) => {
            if(err) throw err
        })
    })

【讨论】:

  • 代码示例让事情变得更加清晰,谢谢。
  • 解决promise然后将MongoClient对象存储在connect var中,而不是每次访问db时都解决不是更好吗?
【解决方案3】:

当前接受的答案是正确的,因为您可以保持相同的数据库连接打开以执行操作,但是,它缺少有关在关闭时如何重试连接的详细信息。以下是自动重新连接的两种方法。它在 TypeScript 中,但如果需要,它可以很容易地转换成普通的 Node.js。

方法一:MongoClient 选项

允许 MongoDB 重新连接的最简单方法是在将 reconnectTries 传递给 MongoClient 时在 options 中定义一个 reconnectTries。任何时候 CRUD 操作超时,它将使用传递给MongoClient 的参数来决定如何重试(重新连接)。将选项设置为Number.MAX_VALUE 实质上是让它永远重试,直到它能够完成操作。如果您想查看将重试哪些错误,您可以check out the driver source code

class MongoDB {
    private db: Db;

    constructor() {
        this.connectToMongoDB();
    }

    async connectToMongoDB() {
        const options: MongoClientOptions = {
            reconnectInterval: 1000,
            reconnectTries: Number.MAX_VALUE
        };

        try {
            const client = new MongoClient('uri-goes-here', options);
            await client.connect();
            this.db = client.db('dbname');
        } catch (err) {
            console.error(err, 'MongoDB connection failed.');
        }
    }

    async insert(doc: any) {
        if (this.db) {
            try {
                await this.db.collection('collection').insertOne(doc);
            } catch (err) {
                console.error(err, 'Something went wrong.');
            }
        }
    }
}

方法二:Try-catch 重试

如果您想在尝试重新连接时获得更精细的支持,您可以使用带有 while 循环的 try-catch。例如,您可能希望在必须重新连接时记录错误,或者您希望根据错误类型执行不同的操作。这也将允许您根据更多条件重试,而不仅仅是驱动程序随附的标准条件。 insert方法可以改成如下:

async insert(doc: any) {
    if (this.db) {
        let isInserted = false;

        while (isInserted === false) {
            try {
                await this.db.collection('collection').insertOne(doc);
                isInserted = true;
            } catch (err) {
                // Add custom error handling if desired
                console.error(err, 'Attempting to retry insert.');

                try {
                    await this.connectToMongoDB();
                } catch {
                    // Do something if this fails as well
                }
            }
        }
    }
}

【讨论】:

  • 顺便说一句! MongoClientOptions 不再有:reconnectInterval: 1000,& reconnectTries: Number.MAX_VALUE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多