防止NodeJS中的MongoDB多个连接

时间:2018-08-24 19:47:27

标签: node.js database mongodb http mongoose

我已经看到了有关该主题的几篇文章;其中之一帮助我进步了-但我仍然有问题。

我的Mongo数据库中充斥着连接并引发错误。我确实有多个使用客户名称建立的不同连接。在网上,我发现了这个有用的课程:

export default class ConnectionManager {
static databases: any = {};

static getConnection(customer: string) : Promise<typeof mongoose> {
    if (this.databases[customer]) return Promise.resolve(this.databases[customer]);

    return new Promise<typeof mongoose>((resolve: any, reject: any) => {
        mongoose.connect(process.env.MONGOOSE_BASE_SERVER_URL + customer, { useNewUrlParser: true })
            .then((newDb: mongoose.Mongoose) => { 
                this.databases[customer] = newDb;
                resolve(this.databases[customer]);
            });
    });
  }
}

正如我所提到的,这很有帮助-如果连接已经存在,它就可以工作。

问题是我有一个计划的任务,该任务可能会在现有连接超时后立即向API发出大量请求。如果此时API充满了请求-它们进入的速度太快,它会打开数百个连接,而我仍然遇到相同的问题;在ConnectionManager.databases有机会使用新连接进行更新之前。

动脑筋想办法避免这种情况。有人有什么建议吗?

谢谢

编辑-认为这主要是在服务重启后发生的。这是一个示例错误:

{ Error: read ECONNRESET
    at TCP.onread (net.js:660:25)
  name: 'MongoNetworkError',
  errorLabels: [ 'TransientTransactionError' ],
  [Symbol(mongoErrorContextSymbol)]: {} }
{ MongoNetworkError: connection 202 to localhost:27017 closed
    at Socket.<anonymous> (.../node_modules/mongodb-core/lib/connection/connection.js:275:9)
    at Object.onceWrapper (events.js:273:13)
    at Socket.emit (events.js:182:13)
    at TCP._handle.close (net.js:599:12)
  name: 'MongoNetworkError',
  errorLabels: [ 'TransientTransactionError' ],
  [Symbol(mongoErrorContextSymbol)]: {} }

1 个答案:

答案 0 :(得分:2)

承诺自然会提供缓存行为,因为已解决的诺言在链接时会提供相同的结果。

一种正确的方法是将诺言存储在{​​{1}}中,这样就不会出现导致多个同名连接(即databases)的竞争条件。

但是对于内部连接连接承诺的猫鼬来说,这不是必需的。连接对象可以保存和使用。使用databases[customer] = Promise.resolve(mongoose.connect(...))方法创建多个连接。

此外,仅静态类是反模式。它可以是一个对象,也可以是一个函数:

createConnection

没有export const _databases = {}; export const getConnection = (customer) => { if (!_databases[customer]) _databases[customer] = mongoose.createConnection( process.env.MONGOOSE_BASE_SERVER_URL + customer, { useNewUrlParser: true } ); return _databases[customer]; } 对象公开导出的明显理由。可以将其导出以进行测试。