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
相关产品推荐
相关产品推荐

