持续打开MongoDB数据库连接


73

在许多使用MongoDB的入门示例中,您将看到类似以下的代码:

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

如果MongoDB像其他任何数据库系统一样,open并且close操作通常在时间上很昂贵。

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

换句话说,openclose不是每次你需要去和做一些与数据库相关的操作-一旦完成。当您实际上完成所有与数据库相关的工作时,您将继续使用db在初始期间返回的对象,而open\connect仅在末尾使用来重用该对象close

显然,由于所有I / O都是异步的,因此在close发出之前,请确保已完成最后一个数据库操作close。似乎这样应该可以,但我想仔细检查一下,以防万一我刚接触MongoDB时遗漏了一些东西。谢谢!


还要检查一下,可能会对您有所帮助
Amol M Kulkarni 2013年

有趣。非常感谢你!
路易斯

Answers:


56

是的,这是正常现象。启动您的应用程序,连接到数据库,对数据库进行长时间的操作,如果连接意外中断,则可能重新连接,然后再也不要关闭连接(仅依赖于进程终止时发生的自动关闭) 。


3
另外,默认情况下,您使用node-mongodb-native获得5个池化连接。查看关于poolSize的文档。
hurrymaplelad

1
彼得,非常感谢您证实我的怀疑,谢谢!
路易斯

6
我按照解决方案stackoverflow.com/a/24634454/3994271进行操作,它与此答案中提到的相同。但是,如果连接意外断开,我们如何自动重新连接?
阿扬(Ayan)

7

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
        })
    })

1
该代码示例使事情变得更加清晰,谢谢。
Wessah,

1
解决promise然后将MongoClient对象存储在connect var中,而不是每次访问db时都要解决,会更好吗?
bulkyPanda

1

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

方法1:MongoClient选项

允许MongoDB重新连接的最简单方法是在将a传入时定义reconnectTriesin 。每当CRUD操作超时时,它将使用传入的参数来决定如何重试(重新连接)。将该选项设置为本质上可以使它永久重试,直到能够完成操作为止。如果要查看重试哪些错误,可以签出驱动程序源代码optionsMongoClientMongoClientNumber.MAX_VALUE

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.');
            }
        }
    }
}

方法2:尝试捕获重试

如果您想获得有关尝试重新连接的更详细的支持,可以将try-catch与while循环一起使用。例如,您可能需要在必须重新连接时记录错误,或者根据错误的类型执行其他操作。除了驱动程序随附的标准条件外,这还使您可以根据更多条件重试。该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
                }
            }
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.