PM2部署后端服务,为什么偶尔会出现连接断开且日志没报错?

极客梦轩 阅读 160

用PM2部署了一个Express服务,最近频繁出现客户端连接突然断开的情况,但PM2日志里完全没有报错。我试过用pm2 restart和检查配置文件,断开问题还是偶尔出现。服务是用cluster模式启动的,代码里也没有明显异常捕获遗漏,这是什么情况?

PM2启动命令是这样的:

pm2 start app.js -i max --name "api-server" --no-daemon

Node.js用了process.on('uncaughtException')unhandledRejection,但日志里都没记录到异常…

我来解答 赞 22 收藏
二维码
手机扫码查看
2 条解答
文鑫 Dev
检查一下是不是负载均衡或反向代理把连接杀了,特别是用了Nginx或者云服务商的LB。加上这些日志看看:

process.on('disconnect', () => {
console.log('PM2 worker disconnected');
});

process.on('exit', (code) => {
console.log(Worker exited with code ${code});
});


同时换用 pm2 start app.js -i max --name "api-server" --no-daemon --trace 开启追踪模式,看看有没有隐藏异常。
点赞 4
2026-02-09 20:10
南宫缤泽
这问题我之前踩过好几次,表面看没报错其实可能是底层连接被悄悄干掉了。你用cluster模式跑的,得先排查几个常见坑。

第一个是负载均衡导致的连接中断。PM2在cluster模式下默认用round-robin调度,如果某个worker进程挂了或者重启,当前连在这个worker上的请求就会直接断开,而且Node层面上未必能捕获到异常,因为连接是操作系统层面被重置的。你可以试试把启动命令改成 pm2 start app.js -i max --name "api-server" --no-daemon --execution-mode cluster 明确指定模式,虽然看着差不多但有时候版本差异会导致行为不同。

第二个重点查的是系统资源限制。调试看看是不是文件描述符被打满了。你在服务器上运行 ulimit -n 看看上限,再用 lsof -p $(pgrep node) | wc -l 查实际占用。如果接近上限,连接就会无声断掉,PM2日志也不会记录这种系统级问题。解决办法是在PM2配置里加环境变量限制,或者改系统配置。

第三个可能性是心跳或超时设置不合理。Express本身不会主动维持长连接,如果你前面还有Nginx、ELB之类的代理,它们一般有60秒到300秒不等的空闲超时。客户端长时间没发数据,代理直接切断,后端根本不知道发生了啥。你可以在Nginx那边调proxy_send_timeout和proxy_read_timeout,或者让客户端定期发心跳包。

最后建议加上更细粒度的日志。你现在只监听uncaughtException和unhandledRejection,但HTTP连接断开可能走的是req.on('close')或者socket的end事件。建议在路由里加一层中间件:

app.use((req, res, next) => {
const clientIp = req.ip || req.connection.remoteAddress
console.log([REQ] ${clientIp} ${req.method} ${req.url})

res.on('close', () => {
if (!res.headersSent) {
console.log([ABORT] Request aborted before response sent: ${req.url})
}
})

res.on('finish', () => {
console.log([DONE] ${res.statusCode} ${req.url})
})

next()
})


这样至少能看到是不是大量请求在中途被关闭。结合服务器时间戳和客户端行为对比一下,基本就能定位是哪一环出的问题了。
点赞 8
2026-02-09 06:00