AWS EC2上NodeJS WebSocket服务器无响应休眠问题排查求助
故障原因分析与排查方向
1. TCP连接资源耗尽
WebSocket基于TCP协议运行,若服务器积累大量TIME_WAIT或CLOSE_WAIT状态的连接,会占满可用端口,导致无法接受新客户端连接。SSH登录操作可能触发内核自动清理超时连接,或刷新网络栈,临时恢复端口可用度。
- 排查动作:
- 定时执行
netstat -anp | grep :<你的WS端口>或ss -tulpn | grep <你的WS端口>,记录端口状态分布 - 检查内核参数:
sysctl net.ipv4.tcp_tw_reuse、sysctl net.ipv4.tcp_fin_timeout,确认是否开启TIME_WAIT连接复用,以及超时时间是否合理(建议fin_timeout设为30秒)
- 定时执行
2. Node.js事件循环阻塞
进程存活但事件循环被长时间阻塞,会导致WebSocket服务无法处理新的连接请求。常见诱因包括:同步IO操作耗时过长、内存泄漏引发频繁GC阻塞、WebSocket回调中存在未捕获的静默错误(未输出到PM2日志)。
- 排查动作:
- 在代码中添加事件循环延迟监控:
setInterval(() => { const start = Date.now(); setImmediate(() => { const delay = Date.now() - start; if (delay > 100) console.warn(`Event loop blocked for ${delay}ms`); }); }, 1000); - 用
pm2 monit实时监控进程的CPU、内存变化,排查是否有异常峰值 - 确保WebSocket实例的
error事件被监听并记录日志,避免静默异常:ws.on('error', (err) => { console.error('WebSocket error:', err); });
- 在代码中添加事件循环延迟监控:
3. AWS EC2网络层静默故障
EC2实例状态显示活跃,但弹性网络接口(ENI)可能出现底层故障,或AWS网络链路临时阻塞。SSH登录时建立的新网络会话会触发ENI重置或路由刷新,恢复监听能力。
- 排查动作:
- 查看CloudWatch的网络指标:
NetworkPacketsIn、NetworkErrors,确认故障时间段是否有数据包丢失或错误突增 - 检查实例安全组、NACL规则是否有临时变更(比如误加了出站限制)
- 尝试手动重置ENI(AWS控制台操作),测试是否能复现“登录即恢复”的效果
- 查看CloudWatch的网络指标:
4. PM2进程监控失效
PM2仅监控进程是否存活,但无法检测到进程内部的服务异常(比如文件描述符耗尽导致无法创建新socket)。此时进程处于僵尸服务状态,PM2仍显示“在线X天”。
- 排查动作:
- 查看进程的文件描述符使用情况:
ls /proc/<你的WS进程PID>/fd | wc -l,对比系统的ulimit -n设置(默认可能是1024,建议调高到65535) - 在PM2配置中添加自定义健康检查脚本,定时向WebSocket服务发送心跳请求,失败则自动重启进程:
{ "apps": [{ "name": "ws-server", "script": "server.js", "env": { "NODE_ENV": "production" }, "health-check": { "url": "ws://localhost:<端口>/health", "interval": 30000, "timeout": 5000, "unhealthy_threshold": 2 } }] }
- 查看进程的文件描述符使用情况:
5. 操作系统资源限制或静默异常
OOM Killer可能标记了进程但未彻底杀死,导致进程处于半存活状态;部分自定义AMI可能存在电源管理设置,触发CPU或网络适配器休眠。
- 排查动作:
- 查看系统日志
/var/log/syslog或/var/log/messages,搜索out of memory关键字,确认是否有OOM触发记录 - 检查系统电源管理设置:
systemctl list-unit-files | grep sleep,确保没有自动休眠的服务 - 开启内存监控,记录进程内存使用峰值:
pm2 logs --raw | grep 'memory'
- 查看系统日志
内容的提问来源于stack exchange,提问作者Glenn Angel
相关产品推荐
相关产品推荐

