Node.js 如何在无服务器设置中可靠地连接到Mongodb?
十分之八的情况下,一切都连接良好。也就是说,我有时会遇到一个Node.js 如何在无服务器设置中可靠地连接到Mongodb?,node.js,mongodb,serverless,vercel,Node.js,Mongodb,Serverless,Vercel,十分之八的情况下,一切都连接良好。也就是说,我有时会遇到一个在调用MongoClient.prototype.db之前必须连接MongoClient的错误。我应该如何更改代码以使其可靠地工作(100%) 我尝试了一段来自Now Zeit平台创建者之一的代码片段 我的经纪人 const { send } = require('micro'); const { handleErrors } = require('../../../lib/errors'); const cors = require(
在调用MongoClient.prototype.db之前必须连接MongoClient的错误。我应该如何更改代码以使其可靠地工作(100%)
我尝试了一段来自Now Zeit平台创建者之一的代码片段
我的经纪人
const { send } = require('micro');
const { handleErrors } = require('../../../lib/errors');
const cors = require('../../../lib/cors')();
const qs = require('micro-query');
const mongo = require('../../../lib/mongo');
const { ObjectId } = require('mongodb');
const handler = async (req, res) => {
let { limit = 5 } = qs(req);
limit = parseInt(limit);
limit = limit > 10 ? 10 : limit;
const db = await mongo();
const games = await db
.collection('games_v3')
.aggregate([
{
$match: {
removed: { $ne: true }
}
},
{ $sample: { size: limit } }
])
.toArray();
send(res, 200, games);
};
module.exports = handleErrors(cors(handler));
我的mongo脚本,在lambda仍然处于热状态时重用连接:
// Based on: https://spectrum.chat/zeit/now/now-2-0-connect-to-database-on-every-function-invocation~e25b9e64-6271-4e15-822a-ddde047fa43d?m=MTU0NDkxODA3NDExMg==
const MongoClient = require('mongodb').MongoClient;
if (!process.env.MONGODB_URI) {
throw new Error('Missing env MONGODB_URI');
}
let client = null;
module.exports = function getDb(fn) {
if (client && !client.isConnected) {
client = null;
console.log('[mongo] client discard');
}
if (client === null) {
client = new MongoClient(process.env.MONGODB_URI, {
useNewUrlParser: true
});
console.log('[mongo] client init');
} else if (client.isConnected) {
console.log('[mongo] client connected, quick return');
return client.db(process.env.MONGO_DB_NAME);
}
return new Promise((resolve, reject) => {
client.connect(err => {
if (err) {
client = null;
console.error('[mongo] client err', err);
return reject(err);
}
console.log('[mongo] connected');
resolve(client.db(process.env.MONGO_DB_NAME));
});
});
};
我需要我的处理程序100%可靠。我也有同样的问题。在我的例子中,这是由于在上一个getDb()调用返回之前调用getDb()引起的。在本例中,我相信'client.isConnected'返回true,即使它仍在连接
这是由于忘记在一个位置的getDb()调用之前放置一个“wait”。我通过使用以下命令从getDb输出一个调用堆栈来跟踪:
console.log(new Error().stack);
我在问题中的示例代码中没有看到相同的问题,尽管它可能是由另一段未显示的代码触发的
if (client && !client.isConnected) {
client = null;
console.log('[mongo] client discard');
}
此代码可能会导致问题!即使您将client
设置为null
,该客户端仍然存在,将继续连接到mongo,不会被垃圾收集,其回调连接代码仍将运行,但是在其回调中,客户端
将引用创建的下一个不一定连接的客户端
这种代码的一种常见模式是只从getDB
调用返回一个承诺:
让clientP=null;
函数getDb(fn){
if(clientP)返回clientP;
clientP=新承诺((解决、拒绝)=>{
客户端=新的MongoClient(process.env.MONGODB_URI{
useNewUrlParser:true
});
client.connect(err=>{
如果(错误){
console.error(“[mongo]客户端错误”,err);
退货拒绝(err);
}
log(“[mongo]connected”);
解析(client.db(process.env.MONGO_db_NAME));
});
});
返回客户;
};
我写了这篇文章,讨论的是无服务器、lambda e db连接。有一些好的概念可以帮助您找到问题的根本原因。还有一些示例和用例说明如何缓解连接池问题
只需查看您的代码,我就可以看出它缺少以下内容:
context.callbackWaitsForEmptyEventLoop = false;
可能是Lambda并行执行的次数太多,而DB服务器不支持那么多打开的并行连接。你能检查一下它的配置吗?您还可以在Lambda级别限制并发性,这是一个很好的观点。你是说你不需要担心没有连接的客户机(因为它会自己尝试再次连接?)你的替换代码无法处理这种情况。我必须显著增加连接重试次数,因为默认情况下,客户端在重试30秒后会放弃。有大量连接设置选项可确保您能够连接(以及在连接丢失时重新连接)--您是否担心丢失连接或无法创建初始连接?您不需要创建多个MongoClientMore来避免连接丢失。但是你是对的,正确的解决方案应该是增加连接重试选项。