我一直在使用Mongoose将Mongodb与我的nextjs应用程序连接起来,在开发模式下一切都很好,但当我部署项目时,即使是一个用户(我)也需要大约60到80个连接。当我与3/4的朋友分享链接时,连接已达到500个连接限制。
下面是我的initDB文件的代码:
import mongoose from "mongoose";
const MONGO_URI = process.env.MONGO_URI;
if (!MONGO_URI) {
throw new Error("Error Code: grx30xd33d");
}
let cached = global.mongoose;
if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}
async function initDB() {
if (cached.conn) {
return cached.conn;
}
if (!cached.promise) {
const opts = {
bufferCommands: false,
useNewUrlParser: true,
useUnifiedTopology: true,
maxPoolSize: 50,
wtimeoutMS: 2500,
useNewUrlParser: true,
};
mongoose.set("strictQuery", false);
cached.promise = mongoose.connect(MONGO_URI, opts).then((mongoose) => {
return mongoose;
});
}
try {
cached.conn = await cached.promise;
} catch (e) {
cached.promise = null;
throw e;
}
return cached.conn;
}
export default initDB;
这是我使用initDB的页面。
import initDB from "../../../helpers/initDB";
import directorySchema from "../../../models/directory/directorySchema ";
export default async function handler(req, res) {
await initDB();
return new Promise(async (resolve, reject) => {
try {
const userProf = await directorySchema
.find()
.limit(20)
.sort({ _id: -1 })
.then(async (response) => {
if (response !== null) {
res.json({
success: true,
data: response,
message: "Data Fetched Successfully",
});
} else {
return res.json({
success: false,
message: "Invalid data response",
});
}
})
.catch((error) => {
console.log(error);
res.json(error);
res.status(405).end();
return reject();
});
} catch (error) {
console.log(error);
}
});
}
响应工作正常,我得到了所需的响应,但在mongodb中达到了连接限制。
这是写这个问题时的连接截图。
1条答案
按热度按时间aelbi1ox1#
**这个问题不是next.js的问题,而是Vercel主机的问题。**正如OP所指出的,这个问题在本地是不可重现的。
问题是Vercel的无服务器特性与厚状态mongodb客户端不太兼容。Mongodb原生nodejs驱动程序被设计为永久运行,管理套接字连接以将其重用于多个请求,跟踪副本集拓扑等。另一方面,Vercel在每个HTTP请求上启动一个新的nodejs进程,这使得无法重用已经打开的连接。
“来自可靠来源的答案”部分:
这个问题正在https://github.com/vercel/next.js/discussions/12229中讨论,在回答这个问题时仍然是开放的。
最实用的建议来自当前的next.js仓库维护者Lee罗宾逊,
您可以使用Mongo的Data API。
https://www.mongodb.com/docs/atlas/api/data-api-resources/
它确实解决了连接池的问题,成本是:
贡献者克里斯·安东尼推荐了一种不那么戏剧性的方法:
1.确保连接被缓存,并且正确处理承诺的连接。- 参见下一个示例[https://github.com/vercel/next.js/blob/canary/examples/with-mongodb/util/mongodb.js](https://github.com/vercel/next.js/blob/canary/examples/with-mongodb/util/mongodb.js)
1.确保您已将客户端配置为终止空闲连接。在不支持maxIdleTimeMS的情况下,socketTimeoutMS也可以。
1.确保关闭所有光标。以前,我让Mongo服务器做这个。但这很可悲现在,我确保首先存储响应,然后手动关闭每个端点上的光标。
例如,在池中有1个连接的配置:
将导致每个http请求1个连接,但驱动程序将无法并行运行请求。您需要尝试使用精确的超时和池大小来找到平衡。
这远远不能有效地使用驱动程序,但至少它将解锁依赖库的使用,如mongoose。
关闭连接有点棘手,如果你在所有查询承诺都被解析之前关闭连接,你会得到“MongoError:拓扑已关闭,请连接”错误。对于Mongoose来说尤其如此,因为它被设计为使用更高的抽象级别,并且不手动管理连接。