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来避免连接丢失。但是你是对的,正确的解决方案应该是增加连接重试选项。