Соединения открыты с MongoDB
Я разрабатываю проект с помощью NextJS и храню свои данные с помощью MongoDB, и у меня проблемы с подключениями MongoDB.
Логика подключения проста:
- Пользователь подключается к странице
- Страница связывается с моим API, чтобы получить информацию о странице
- Мой 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