NodeJS Express应用如何处理MongoDB数据库连接丢失问题
优化方案
1. 全局监听MongoDB连接状态,启用自动重连
Mongoose本身提供了连接生命周期事件监听能力,不需要在每次数据库操作时单独判断连接错误。Mongoose 6+默认已经开启自动重连,你可以自定义重连策略,遇到断开事件只需要打日志即可,不需要直接终止进程,重连成功后会自动恢复数据库操作能力。
const mongoose = require('mongoose'); const { MongoNetworkError, MongooseServerSelectionError } = require('mongoose').Error; // 连接配置,自定义重连参数 const mongoConnectOptions = { maxPoolSize: 10, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 45000, // 自动重连相关配置,可按需调整 reconnectTries: Number.MAX_VALUE, reconnectInterval: 1000, }; // 初始化连接 mongoose.connect(process.env.MONGO_URI, mongoConnectOptions); // 全局监听连接事件 const db = mongoose.connection; db.on('error', (err) => { if (err instanceof MongoNetworkError || err instanceof MongooseServerSelectionError) { console.error('Mongo | Mongoose 网络连接错误,将自动尝试重连', err.message); } else { console.error('MongoDB 连接错误', err); } }); db.on('disconnected', () => console.warn('MongoDB 连接断开,正在尝试重连')); db.on('reconnected', () => console.info('MongoDB 重连成功')); db.on('connected', () => console.info('MongoDB 连接成功'));
2. 封装异步路由错误捕获中间件,统一处理异常
不用每个路由都编写重复的try/catch逻辑,用高阶函数包装所有异步路由处理器,自动捕获异常后传递给全局错误处理中间件即可。
// 异步路由错误捕获 wrapper const asyncHandler = (fn) => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); };
3. 全局错误处理中间件,统一拦截Mongo相关错误
所有路由抛出的错误都会走到该中间件,统一判断错误类型返回对应响应,不需要每个路由单独处理连接类错误。
// 注意错误处理中间件必须是4个参数,Express会自动识别 app.use((err, req, res, next) => { // 统一处理MongoDB连接相关错误 if (err instanceof MongoNetworkError || err instanceof MongooseServerSelectionError) { console.error('请求处理过程中出现MongoDB网络错误', err.message); // 返回503服务不可用状态码,告知客户端稍后重试,不需要终止进程 return res.status(503).json({ code: 503, msg: '服务暂时不可用,请稍后重试' }); } // 其他业务错误处理逻辑 console.error('服务内部错误', err); res.status(500).json({ code: 500, msg: '服务内部错误' }); });
4. 优化后的路由写法
改造后路由不需要再写冗余的错误捕获和判断逻辑:
const registerCustomer = asyncHandler(async (req, res) => { const validRegistrationCode = await CustomerRegistrationCode.findOne({ code: req.body.code }); return res.json({ obj: validRegistrationCode }); });
可选优化:添加连接状态预检中间件
如果需要在请求进入业务逻辑前就拦截断连场景,可以新增全局预检中间件:
app.use((req, res, next) => { // mongoose.connection.readyState取值:0=断开、1=已连接、2=连接中、3=断开中 if (mongoose.connection.readyState !== 1) { return res.status(503).json({ code: 503, msg: '服务暂时不可用,请稍后重试' }); } next(); });
注意:不建议遇到Mongo连接错误就直接调用process.exit(1)终止进程,Mongoose的自动重连机制会在网络恢复后自动重建连接,终止进程反而会导致服务完全不可用,需要人工重启才能恢复。
内容的提问来源于stack exchange,提问作者swftowu69
相关产品推荐
相关产品推荐

