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

NestJS部署Lambda连接MongoDB时连接数过多问题求助

解决NestJS Lambda服务中Mongoose连接重复创建的问题

问题根源

  1. REQUEST作用域的配置服务:原MongooseConfigService使用Scope.REQUEST,导致每次请求都会实例化该服务,触发createMongooseOptions重新生成连接配置,进而创建新的Mongoose连接。
  2. 错误的配置时机:MongooseModule.forRootAsync在模块初始化阶段执行,此时还没有请求上下文,无法正确获取请求中的dbName;即使改为Scope.DEFAULT,也会因为初始化时无请求参数导致配置无效。
  3. 未复用连接:原方案没有对不同dbName的连接或数据库实例进行缓存,每次请求都新建资源。

解决方案

方案1:复用底层连接,动态切换数据库(推荐)

利用Mongoose的useDb()方法,基于同一个基础连接切换不同的数据库,自动缓存数据库实例,避免重复创建TCP连接。

1. 创建连接管理器服务

import { Injectable } from '@nestjs/common';
import * as mongoose from 'mongoose';

@Injectable()
export class MongooseDbManager {
  // 初始化默认基础连接(无特定dbName)
  private readonly baseConnection: mongoose.Connection;

  constructor() {
    this.baseConnection = mongoose.createConnection(process.env.MONGO_URL, {
      // 适配Lambda场景的连接池配置
      poolSize: 5,
      maxPoolSize: 10,
      minPoolSize: 1,
    });
  }

  // 根据dbName获取对应的数据库实例,useCache自动缓存
  getDatabase(dbName: string): mongoose.Db {
    if (!dbName) {
      throw new Error('dbName is required');
    }
    return this.baseConnection.useDb(dbName, { useCache: true });
  }
}

2. 在业务服务中使用动态数据库

import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import * as mongoose from 'mongoose';
import { MongooseDbManager } from './mongoose-db.manager';

@Injectable()
export class DataService {
  constructor(private readonly dbManager: MongooseDbManager) {}

  async fetchData(request: Request) {
    // 解析请求体
    if (Buffer.isBuffer(request.body)) {
      request.body = JSON.parse(request.body.toString());
    }
    const { db } = request.body;

    // 获取目标数据库实例
    const targetDb = this.dbManager.getDatabase(db);
    // 获取模型(确保模型在数据库实例上注册)
    const YourModel = targetDb.model('YourModel');

    // 执行数据库操作
    return YourModel.find().limit(10).exec();
  }
}

3. 模块配置

移除原有的MongooseModule.forRootAsync配置,直接引入自定义的连接管理器:

import { Module } from '@nestjs/common';
import { MongooseDbManager } from './mongoose-db.manager';
import { DataService } from './data.service';

@Module({
  providers: [MongooseDbManager, DataService],
  exports: [DataService],
})
export class DatabaseModule {}

方案2:缓存不同dbName的独立连接

如果需要为每个dbName创建独立连接(资源消耗较大,非推荐),可以通过Map缓存已创建的连接:

import { Injectable } from '@nestjs/common';
import * as mongoose from 'mongoose';

@Injectable()
export class MongooseConnectionManager {
  private readonly connections = new Map<string, mongoose.Connection>();

  async getConnection(dbName: string): Promise<mongoose.Connection> {
    if (!dbName) {
      throw new Error('dbName is required');
    }

    // 缓存中存在则直接返回
    if (this.connections.has(dbName)) {
      return this.connections.get(dbName);
    }

    // 创建新连接并缓存
    const connection = await mongoose.createConnection(process.env.MONGO_URL, {
      dbName,
      poolSize: 5,
    });
    this.connections.set(dbName, connection);
    return connection;
  }
}

Lambda场景注意事项

  • 连接池配置:Lambda容器可能被复用,合理设置连接池大小(如poolSize:5)避免资源浪费;容器销毁时连接会自动释放。
  • 避免冷启动延迟:首次请求会创建连接,后续复用容器时直接使用已有的连接/数据库实例。
  • 错误处理:添加连接异常捕获,处理连接断开等情况,必要时清除缓存重新创建。

内容的提问来源于stack exchange,提问作者Hamza Afridi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:35:50