问题描述
我正在使用 NextJS 开发一个项目,并使用 MongoDB 存储我的数据,但在 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