0

我正在使用NextJS开发一个项目,并将我的数据存储在MongoDB中,并且遇到 MongoDB 连接问题。

连接逻辑很简单:

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

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

PS 当我关闭我的本地项目时,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 教程中获取了上面的代码

我应该怎么办?

4

3 回答 3

3

问题在于 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 示例存储库中查看完整示例

于 2021-07-13T11:02:55.023 回答
0

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

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

  const mongoClient = new MongoClient(process.env.mongoApiUrl, {
    useNewUrlParser: true,
    useUnifiedTopology: 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;
于 2021-07-13T14:43:30.353 回答
0

考虑到下一个连接的新变化,这就是我根据以前的代码使它工作的方式

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, {
    useNewUrlParser: true,
    useUnifiedTopology: 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(MONGODB_DB),
            }
        })
        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
于 2021-07-27T12:49:02.653 回答