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

Serverless Node.js函数中Mongoose连接MongoDB突然失效求助

Serverless + Mongoose 连接MongoDB生产环境失效问题

我的Serverless应用通过Mongoose连接MongoDB,正常运行数月后昨日突然失效。本地使用serverless-offline测试一切正常,但部署到AWS生产环境后,调用接口会出现502及CORS错误。


数据库连接代码(database.js)

// database.js
const mongoose = require('mongoose');

const connect = async (uri) => {
  try {
    mongoose.set("strictQuery", true)

    mongoose.connect(uri)
  
    mongoose.connection.on('connected', () => {
      console.log("Connected to database...");
    });
    
    mongoose.connection.on('disconnected', () => {
      console.log('Disconnected from database...');
    });
    
    process.on('SIGINT', () => {
      mongoose.connection.close(() => {
        console.log("Connection closed...");
        
        process.exit(0);
      });
    });
  } catch(error) {
    console.log(error)
  }
}

module.exports.connect = connect;

函数中调用连接的代码

const User = require("../models/User")
const bcrypt = require("bcryptjs")
const _ = require("lodash")
const jwt = require("jsonwebtoken")
const { connect } = require("../database")

connect(process.env.DATABASE)

module.exports.handler = async (event) => {
  let headers = {
    "Access-Control-Allow-Origin": event.headers.origin,
    "Access-Control-Allow-Credentials": true
  }

  ...other code
}

CloudWatch日志截图

日志截图


问题排查与修复方案

1. 核心问题:异步连接未正确等待

你的connect函数声明为async,但调用mongoose.connect(uri)时未加await,且直接在函数外部执行connect(process.env.DATABASE),没有等待连接建立就进入handler逻辑。AWS Lambda的冷启动特性会导致业务逻辑在数据库连接完成前就运行,触发数据库操作失败,最终引发502错误。

修复代码:

修改database.js(添加单例连接+异步等待)

// database.js
const mongoose = require('mongoose');

// 维护单例连接,避免Lambda冷启动重复创建连接
let isConnected = false;

const connect = async (uri) => {
  if (isConnected) {
    console.log("复用已有数据库连接...");
    return;
  }
  try {
    mongoose.set("strictQuery", true);
    // 等待连接完成
    await mongoose.connect(uri);
    isConnected = true;
    console.log("Connected to database...");
    
    mongoose.connection.on('disconnected', () => {
      console.log('Disconnected from database...');
      isConnected = false;
    });

    // Lambda环境无需监听SIGINT信号,移除该逻辑
  } catch(error) {
    console.error("数据库连接失败:", error);
    throw error; // 抛出错误让handler捕获处理
  }
}

module.exports.connect = connect;

修改handler代码(先确保连接成功再执行业务)

const User = require("../models/User")
const bcrypt = require("bcryptjs")
const _ = require("lodash")
const jwt = require("jsonwebtoken")
const { connect } = require("../database")

module.exports.handler = async (event) => {
  // 完善CORS头部,兼容预检请求与异常场景
  const headers = {
    "Access-Control-Allow-Origin": event.headers?.origin || "*",
    "Access-Control-Allow-Credentials": true,
    "Access-Control-Allow-Headers": "Content-Type, Authorization"
  }

  // 处理OPTIONS预检请求
  if (event.httpMethod === "OPTIONS") {
    return { statusCode: 200, headers };
  }

  try {
    // 先等待数据库连接成功
    await connect(process.env.DATABASE);
    
    // ...你的业务逻辑代码
    // 示例:查询用户
    const user = await User.findOne({ email: JSON.parse(event.body).email });
    
    return {
      statusCode: 200,
      headers,
      body: JSON.stringify({ success: true, data: user })
    }
  } catch (error) {
    console.error("接口处理失败:", error);
    return {
      statusCode: 500,
      headers,
      body: JSON.stringify({ success: false, message: "服务器内部错误" })
    }
  }
}

2. CORS错误关联修复

502错误会导致API Gateway返回的响应缺失正确CORS头部,进而触发浏览器的CORS报错。修复数据库连接问题后,只要handler能正常返回带合规CORS头部的响应,CORS错误会自动解决。额外注意:

  • 必须单独处理OPTIONS预检请求,返回200状态码
  • 若需携带Cookie,Access-Control-Allow-Origin不能设为*,需验证请求origin是否在白名单内

3. Lambda环境适配建议

  • Lambda执行环境短暂,无需监听SIGINT这类本地环境信号,依赖Mongoose自带的自动重连机制即可
  • 保留Mongoose默认连接池配置,提升连接复用率,降低冷启动开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:27:47