【问题标题】:Mongo DB problem - connections accumulationMongodb问题——连接积累
【发布时间】:2021-07-06 16:29:02
【问题描述】:

我连接到 Mondo DB 的方法有问题。

我使用以下方法:

import { Db, MongoClient } from "mongodb";

let cachedConnection: { client: MongoClient; db: Db } | null = null;

export async function connectToDatabase(mongoUri?: string, database?: string) {
  if (!mongoUri) {
    throw new Error(
      "Please define the MONGO_URI environment variable inside .env.local"
    );
  }

  if (!database) {
    throw new Error(
      "Please define the DATABASE environment variable inside .env.local"
    );
  }

  if (cachedConnection) return cachedConnection;

  cachedConnection = await MongoClient.connect(mongoUri, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  }).then((client) => ({
    client,
    db: client.db(database),
  }));

  return cachedConnection!;
}

每当我需要连接到 MongoDB 时,我都会执行以下操作:

const { db } = await connectToDatabase(config.URI, config.USERS_DATABASE);
const myUniversity = await db
  .collection(config.MY_COLLECTION)
  .findOne({})

一切正常,那么有什么问题

问题是与我的数据库的连接在我使用它们后没有关闭。事实上,我认为我的服务器是无状态的,所以每次使用数据库后,连接都会结束。但事实并非如此!他们还活着,并且在使用我的应用程序 mongo atlas 几个小时后给我发了一封电子邮件,说超出了限制。

正如您在此屏幕截图中所见,此图表一直在增长。这意味着连接保持不变并且它们积累。你觉得我能怎么解决这个问题?

请记住,只有当我使用相同的连接时,它才会使用cachedConnection。如果我调用与第一个不同的 API,它会创建另一个连接并且它不会进入 if (cachedConnection) 块,但它会一直前进到最后。

【问题讨论】:

  • 一个连接通常代表一个连接池(又名连接池)。 NodeJS 的连接池默认值为 10(取决于驱动程序软件)。 API 还有一个close 方法——关闭连接。请参阅MongoDB NodeJS Connection Guide
  • 好的,但我用两个参数调用该方法,它不会返回一个“客户端”。你的意思是我必须做const { db, client } = await connectToDatabase(config.MY_URI, config.MY_DB);}?每次使用后我都必须做client.close()?这样做缓存的连接将不再可用,对吧?
  • MongoClient.connect(mongoUri... 为您提供连接对象(和池),因此您可以使用它从多个应用程序/功能的 NodeJS 程序连接到服务器。它可以存储和重复使用。通常,您使用应用程序将其关闭。不需要每次操作、查询等都MongoClient.connect(mongoUri...,关闭再重新连接。
  • 好的,但是在这种情况下我该怎么做呢?我该如何存储它?我尝试解构clientclient.close() 抛出“拓扑已关闭,请重新连接”

标签: javascript node.js typescript mongodb


【解决方案1】:

您可以尝试这个简单的演示,它允许您在整个应用程序的不同模块中使用相同的连接。共有三个模块:index.js 是启动程序,dbaccess.js 是您有代码来创建和维护可以一次又一次使用的连接的地方,以及一个apis.js 模块,您可以在其中使用数据库连接到检索数据。

index.js:

const express = require('express');

const mongo = require('./dbaccess');
const apis = require('./apis');

const app = express();

const init = async () => {
    await mongo.connect();
    app.listen(3000);
    apis(app, mongo);
};

init();

dbaccess.js:

const { MongoClient } = require('mongodb');

class Mongo {
    constructor() {
        this.client = new MongoClient("mongodb://127.0.0.1:27017/", {
            useNewUrlParser: true,
            useUnifiedTopology: true
        });
    }

    async connect() {
        await this.client.connect();
        console.log('Connected to MongoDB server.');
        this.db = this.client.db('test');
        console.log('Database:', this.db.databaseName);
    }
}

module.exports = new Mongo();

apis.js:

module.exports = function(app, mongo) {
    app.get('/', function(req, res) {
        mongo.db.collection('users').find().limit(1).toArray(function(err, result) {
            res.send('Doc: ' + JSON.stringify(result));
        });
    });
}

在尝试之前更改 url、数据库名称和集合名称中的适当值。

【讨论】:

  • 您可以在apis.jsdao.js 模块中进一步重构此数据库查询代码。
猜你喜欢
  • 2015-01-06
  • 2022-06-10
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
相关资源
最近更新 更多