与 MongoDB 的连接是开放的

问题描述

我正在使用 NextJS 开发一个项目,并使用 MongoDB 存储我的数据,但在 MongoDB 连接方面存在问题。

连接逻辑很简单:

  1. 用户连接到页面
  2. 页面联系我的 API 以获取页面信息
  3. 我的 API 使用中间件从 MongoDB 获取数据

按照逻辑,我只有一个用户连接到mongoDB(系统用户)。但问题是我在 MongoDB 中打开了很多连接(请参阅 picture)。看来我的中间件没有关闭连接。这是我的代码有问题还是 MongoDB 逻辑的问题?

附言当我关闭本地项目时,MongoDB 连接数下降到 0。

这是我的中间件示例,其中系统连接了 MongoDB。

import { MongoClient } from 'mongodb';
import nextConnect from 'next-connect';

const client = new MongoClient(process.env.mongoApiUrl,{
  useNewUrlParser: true,useUnifiedTopology: true,});

async function database(req,res,next) {
  if (!client.isConnected()) await client.connect();
  req.dbClient = client;
  req.db = client.db('test');
  return next();
}

const middleware = nextConnect();

middleware.use(database);

export default middleware;

根据我的代码,如果我们有一个开放的连接 - 使用开放的连接。我从这个 mongodb tutorial

获取了上面的代码

我该怎么办?

解决方法

问题在于 API 路由是 serverless,这意味着它们在需要时创建,并在底层无服务器托管结构认为合适时销毁。因此,您需要找到一种不为每个请求创建到数据库的连接的方法。

/**
 * Global is used here to maintain a cached connection across hot reloads
 * in development. This prevents connections from growing exponentially
 * during API Route usage.
 */

let cached = global.mongo

if (!cached) {
  cached = global.mongo = { conn: null,promise: null }
}

export async function connectToDatabase() {
  if (cached.conn) {
    return cached.conn
  }

  if (!cached.promise) {
    const opts = {
      useNewUrlParser: true,useUnifiedTopology: true,}

    cached.promise = MongoClient.connect(MONGODB_URI,opts).then((client) => {
      return {
        client,db: client.db(MONGODB_DB),}
    })
  }
  cached.conn = await cached.promise
  return cached.conn
}

您可以在 Next.js examples repository

中查看完整示例 ,

在这里,我重新设计了我的中间件以使用缓存的连接。 (感谢this answer

  import { MongoClient } from 'mongodb';
  import nextConnect from 'next-connect';

  const mongoClient = new MongoClient(process.env.mongoApiUrl,{
    useNewUrlParser: true,});

  //with serverless we need to use cache to prevent re-opening connection
  let cached = global.mongo


  if (!cached) {
    cached = global.mongo = { conn: null,promise: null }
  }

  async function database(req,res,next) {
    if (!cached.promise) {
      cached.promise = mongoClient.connect().then((client) => {
        return {
          client,db: client.db(process.env.MONGODB_DB),}
      })
      cached.conn = await cached.promise
    }

    req.dbClient = cached.conn.client
    req.db = cached.conn.db

    return next();
  }

  const middleware = nextConnect();

  middleware.use(database);


  export default middleware;
,

鉴于 next-connect 的新变化,这就是我根据以前的代码使其工作的方式

import { MongoClient } from 'mongodb';
import nc from 'next-connect';

const MONGODB_URI = process.env.MONGODB_URI
const MONGODB_DB = process.env.MONGODB_DB

const mongoClient = new MongoClient(MONGODB_URI,});

//with serverless we need to use cache to prevent re-opening connection
let cached = global.mongo


if (!cached) {
    cached = global.mongo = { conn: null,promise: null }
}

async function database(req,next) {
    if (!cached.promise) {
        cached.promise = mongoClient.connect().then((client) => {
            return {
                client,}
        })
        cached.conn = await cached.promise
    }

    req.dbClient = cached.conn.client
    req.db = cached.conn.db

    return next();
}

const middleware = nc();

middleware.use(database);


export default middleware;

和我的 .env 文件:

MONGODB_URI=mongodb://localhost:27017/
MONGODB_DB=hotelcrud

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...