Nodejs 进程无响应了,应该怎么查

Nodejs 进程无响应了,应该怎么查

最近在对服务做测试,然后就发现 websocket 连接保持不动的话,过一阵 node 进程就无响应了
表现就是请求端口无响应,LISTEN 的 Recv-Q 不掉
然后在代码里面加入的 setInterval 然后打印也突然不输出了,看样子像是事件循环卡住了

[root /]# ss -ltn
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN     261    511                      :::4000                    :::* 

保持的连接数也不多,才 8 千。也不怎么发送数据,也就半分钟发一条一个字符的 webscoket 数据
连接断开之后,程序也是不继续走,然后就是一堆的 CLOSE_WAIT

内存和 CPU 看上去也没啥异样
最最奇葩的一点是,一旦我使用 pstack 或者 strace ,或者用 kill ,进程就恢复正常了
这是堆栈信息: https://pastebin.com/VJ4ekuQR

Maximum number of open file descriptors 、nr_open 之类的也看过了,都是 6 万多


24 回复

补充一下,测试机和服务器中间是有 ALB 的,走的公网连接,ALB 有定时使用 HEAD 根目录检测存活机制,不知道有没有影响
客户端定时发送的数据也是一直有日志的,服务端能收到,直到服务出问题就没了
从开始连接到服务出问题,出问题的时长基本都在 15 分钟到 30 分钟
unhandledRejection 和 uncaughtException 全程也没有任何东西

NodeJs 的版本是 v16.12.0 ,在 https://nodejs.org/dist/下载的



我一开始也以为是 CLOSE_WAIT 的问题,现在看来 CLOSE_WAIT 只是结果
在我测试机断开连接之前,服务器上是没有 CLOSE_WAIT 状态的连接的,服务更像是“卡住了”,就连 setInterval 都没有执行

刚刚把主要的业务代码去掉了,测试依旧出问题
感觉不像是代码有问题,更像是系统配置不太对或者 NodeJs 的 BUG
后面我再简化下放一下代码


epoll 性能应该没这么差, 我看堆栈信息上显示好像是大量的占用了 Queue, 具体为什么大量占用 Queue 就要看代码了

应该不是,你说的这种情况现象应该会表现为 cpu 占满,我这边没有观察到这个现象,并且一旦我使用 pstack 或者 strace ,就能恢复正常,也不支持你这个观点

Queue 不一定会 cpu 占满, 我看到这边堆栈信息好像有大量的 Queue , 我有很有理由怀疑是这块。epoll 的响应很快的.

错误的代码导致大量占用 Queue 造成 Event loop 等待, 这是 NodeJS 中新手很容易犯的错误。

Event loop 等待并不表示 CPU 会占满。 但是 CPU 占满 Event loop 一定会等待

你可以放个测试用例和最小的可复现的仓库, 我可以帮你分析下

nodejs 可以 pstack 看调用栈吗。

目前重现的条件还不是特别清楚,所以还不好弄


感谢回复,根据你的提醒我去查了一下 gc 日志,看起来好像真的有问题
“525695.2 / 0.0 ms”这条是卡住了之后,我执行 pstack 才有的
https://pastebin.com/0anu1851



另外换了几个版本 12 、14 、16 ,都有问题应该可以初步排除 NodeJs 的 bug

这个问题非常好查, 看一下代码就好了。nodejs Queue 导致的情况无非就几种情况

websocket 是好用,主要还是防止内部队列拥挤,以前经常碰到这个问题;
改用队列来处理后,这些毛病很容易被发现。


问题复现了,应该是 glibc 的 bug ,复现代码在这里:
https://pastebin.com/VDi2Vtc4

glibc 版本是 2.17

lz 后来确定是这么底层的问题吗?怎么解决的

可以自行看一下更新记录,是 fork 造成的死锁问题

可以看到出问题时候的现象和堆栈一模一样。后来是用 preload 解决的,其实用 docker 也行


和很多人想的不一样,底层也会出现很多 bug 的,如果做过底层就知道,当然这话不是我说的

大佬,我碰到这样一种情况

大佬,我碰到这样一种情况

cpu 100%,机器大量 CLOSE_WAIT

应该从哪块排查

CPU100%,那就从 CPU 查起呗,看看 CPU 在干嘛

针对Node.js进程无响应的问题,可以按照以下步骤进行排查:

  1. 检查内存使用情况

    • 使用process.memoryUsage()方法检查内存使用情况,看是否存在内存泄漏。
    • 使用Node.js的内置工具--inspect进行内存快照分析。
  2. 检查长时间运行的同步任务

    • 长时间运行的同步任务会阻塞事件循环,导致Node.js进程无响应。
    • 优化代码,将长时间运行的任务拆分为多个小任务,并使用setImmediatesetTimeout将它们放入事件循环的队列中。
  3. 检查第三方库或依赖

    • 使用的第三方库或模块可能存在bug或性能问题。
    • 定期更新第三方库到最新版本,并检查库的issue跟踪器,看是否有已知的性能问题或bug。
  4. 检查系统资源限制

    • 操作系统可能对进程的资源(如文件描述符、内存)设置了限制。
    • 使用ulimit命令检查并调整操作系统的资源限制。
  5. 检查网络问题

    • 网络请求超时或被阻塞也会导致进程无响应。
    • 设置合理的请求超时时间,并使用重试机制来处理可能的网络故障。

以下是一个简单的Node.js代码示例,演示了如何避免长时间运行的同步任务:

const http = require('http');
http.createServer((req, res) => {
  setTimeout(() => {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
  }, 0);
}).listen(8080);
console.log('Server running at http://127.0.0.1:8080/');

通过以上步骤,可以有效地诊断和解决Node.js进程无响应的问题。

回到顶部