Node.js搭配MongoDB与负载均衡时出现socket hang up错误如何解决?
问题根因定位&解决步骤
1. Express中间件顺序错误(首要问题)
你当前app.js里的中间件注册顺序完全颠倒:
// 错误执行顺序:先注册路由、错误处理,再注册解析中间件 app.use('/client', clientRoute); app.use('/reservations', reservationsRoute); app.use('/', ...); app.use(错误处理中间件); // 最后才注册请求解析中间件 app.use(morgan("dev")); app.use(bodyParser.json());
Express中间件按照代码书写顺序从上到下执行:
- 访问根路由
/时不需要解析请求体,直接返回内容,所以响应正常 - 访问
/client、/reservations等业务路由时,bodyParser.json()还未执行,请求无法被解析一直挂起,超时后连接被强制断开,就触发了ECONNRESETsocket挂断错误。
修复方法:把通用中间件注册移到所有路由、错误处理中间件的最前面:
// 正确执行顺序:先注册通用中间件 app.use(morgan("dev")); app.use(bodyParser.json()); // 再注册业务路由 app.use('/client', clientRoute); app.use('/reservations', reservationsRoute); app.use('/', (req, res) =>{ res.send('Welcome to the app'); }); // 最后注册错误处理中间件 app.use((req, res, next) => { const error = new Error("Not found "); error.status = 404; // 原有代码写错为400,404才对应资源未找到 next(error); }) app.use((error, req, res, next) => { res.status(error.status || 500); res.json({ error: { message:("Error 2 - " + error.message ) } }); });
2. 数据库连接代码语法错误
你的数据库连接文件里mongoose.connect参数写法错误,配置项被写到了connect方法外面,且回调和await语法混用:
// 错误写法 connection = await mongoose.connect("removed", () => console.log("Mongo is up and running")),{ useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true }
同时app.js里sslServer启动的catch块存在语法错误,字符串换行导致不闭合,且res在该作用域不存在,不能调用res方法:
// 错误写法 .catch(err =>{ console.log(err) res.status(500).json({ error:err, message: " It went wrong here " }) })
修复方法:
首先修正数据库连接代码:
const mongoConnection = async () => { if (!connection) { connection = await mongoose.connect("removed", { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true }); console.log("Mongo is up and running"); } return connection; }
再修正sslServer启动的catch逻辑:
.catch(err =>{ console.log('数据库连接失败:', err); process.exit(1); // 连接失败直接退出进程,避免无效服务被注册 })
3. 代理错误监听缺失
你的负载均衡代码没有监听proxy的错误事件,如果后端服务响应异常,代理会直接抛出未捕获错误导致连接断开,需要补充错误监听逻辑:
// 在负载均衡代码创建proxy实例后补充: proxy.on('error', (err, req, res) => { console.error('代理错误:', err); if (!res.headersSent) { res.status(503).send('后端服务不可用'); } });
4. 额外校验点
- 直接访问后端服务端口测试
/client等路由是否正常,排除业务路由本身的问题 - 在负载均衡的请求处理逻辑中打印转发的target地址,确认seaport注册的后端服务host、端口正确
- 检查业务路由代码中是否有遗漏
next()调用、未处理的异步错误导致请求挂起
内容的提问来源于stack exchange,提问作者Greatdane14
相关产品推荐
相关产品推荐

