You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS/Vercel集成MongoDB:单开发会话引发连接数持续激增

NextJS + MongoDB 连接数持续暴涨问题排查与解决

问题描述

我在Vercel上运行NextJS应用,通过NextJS的API目录连接MongoDB。仅开启一个开发会话且使用量极低,但MongoDB的连接数持续增长,经常突破300个。请问该问题的原因是什么,如何限制连接数?

原相关代码

客户端初始化代码(lib/mongoClient.ts)

//lib/mongoClient.ts
import { MongoClient } from 'mongodb'

const options = { maxPoolSize: 20 }

let dbclient
let clientPromise

// In production mode, it's best to not use a global variable.
dbclient = new MongoClient(process.env.MONGODB_URI as string, options)
clientPromise = dbclient.connect()

// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default clientPromise

API使用示例1(api/posts/fetch.ts)

//api/posts/fetch.ts
import clientpromise from '../../../lib/mongoClient';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { username } = req.body;
    const client = await clientpromise;
    const db = client.db();
    const posts = await db.collection('posts').find({username:username}).sort({ date: -1 }).toArray();
  }
}

API使用示例2(api/plans/edit.ts)

//api/plans/edit.ts
import { ObjectId } from 'mongodb';
import clientpromise from '../../../lib/mongoClient';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { planid, desc } = req.body;
    try {
      const client = await clientpromise;
      const plans = client.db().collection('plans');
      await plans.findOneAndUpdate(
        { _id: new ObjectId(planid) },
        { $set: { desc } },
        { returnOriginal: false }
      )
    } catch (err) {
      // 建议添加错误处理
      res.status(500).json({ error: err.message })
    }
  }
}

问题原因

  • Vercel无服务器函数的冷启动特性:Vercel会为每个API请求创建独立的函数实例,原代码没有对客户端实例做全局缓存,导致每个新实例都创建一个全新的MongoClient,每个客户端自带20个连接的连接池,多个实例叠加后总连接数迅速突破限制。
  • 错误的全局变量使用逻辑:原代码注释提到生产环境最好不用全局变量,但在Vercel的无服务器环境下,恰恰需要用全局变量来跨函数实例复用客户端,否则每次冷启动都会重复初始化连接池。

解决方法

1. 全局缓存MongoClient实例

修改lib/mongoClient.ts,利用Node.js全局变量缓存客户端,避免重复创建:

// lib/mongoClient.ts
import { MongoClient } from 'mongodb'

const options = {
  maxPoolSize: 20,
  maxIdleTimeMS: 300000 // 新增:5分钟后自动关闭空闲连接
}

let clientPromise: Promise<MongoClient>

// 针对无服务器环境,用全局变量缓存客户端实例
if (!global._mongoClientPromise) {
  const client = new MongoClient(process.env.MONGODB_URI as string, options)
  global._mongoClientPromise = client.connect()
}
clientPromise = global._mongoClientPromise

export default clientPromise

TypeScript用户需添加全局类型声明,在项目根目录创建global.d.ts:

declare global {
  var _mongoClientPromise: Promise<MongoClient> | undefined
}

export {}

2. 优化连接池参数

  • maxPoolSize:根据实际请求量调整,10-20足够应对低流量场景
  • maxIdleTimeMS:设置空闲连接超时时间,让长时间不用的连接自动释放,避免占用资源
  • 可选参数minPoolSize:设为0,避免维持不必要的空闲连接

3. 完善错误处理

在API函数中添加错误处理逻辑,确保异常情况下不会导致潜在的连接泄漏(连接池会自动管理,但完善的错误处理能避免额外问题)。


内容的提问来源于stack exchange,提问作者Sam Y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:54:59