Соединения открыты с MongoDB

Я разрабатываю проект с помощью 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

Что мне делать?

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

Здесь я переработал свое промежуточное ПО, чтобы использовать кешированные соединения. (благодаря этому ответу )

        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;

учитывая новые изменения при следующем подключении, я сделал так, чтобы он работал на основе предыдущего кода

      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
Другие вопросы по тегам