我对运行生产 node.js 应用程序比较陌生,最近我的服务器超时出现问题。
基本上在一定的使用量和时间后,我的 node.js 应用程序停止响应请求。我什至看不到在我的控制台上触发路由 - 就像整个事情都停止了,来自我的客户端(运行 AFNetworking 的 iPhone)的 HTTP 调用不再到达服务器。但是如果我重新启动我的 node.js 应用程序服务器,一切都会重新开始工作,直到事情不可避免地再次停止。该应用程序永远不会崩溃,它只是停止响应请求。
我没有收到任何错误,而且我确保处理和记录所有数据库连接错误,所以我不确定从哪里开始。我认为这可能与内存泄漏有关,所以我安装了 node-memwatch 并为内存泄漏设置一个监听器,但在我的服务器停止响应请求之前不会被调用。
关于可能发生什么以及我如何解决这个问题的任何线索?
这是我的堆栈:
再一次,上面提到的任何模块都没有发生错误。
最佳答案
首先,您需要更具体地了解超时。
现在,有很多很多可能的原因......
Content-Length: 20
的请求 header ,这意味着“我将向您发送 20 个字节”。如果您发送 19 个,另一端将等待剩余的 1 个。如果这需要太长时间...超时。 (total load / # of CPU cores)
大于 1,或者您的内存使用率很高,您的系统可能容量过大。但是请继续阅读... IncomingMesage
对象(又名:在 express 代码中通常称为 req
)将保持被其他对象引用(例如:express 本身)。这些对象中的每一个都可以使用大量内存。 对于内存泄漏,症状是:
Node 进程将使用越来越多的内存。
更糟糕的是,如果可用内存不足并且您的服务器被错误配置为使用交换,Linux 将开始将内存移动到磁盘(交换),这是非常 I/O 和 CPU 密集型的。服务器不应启用交换。
cat /proc/sys/vm/swappiness
将返回您系统中配置的交换级别(从 0 到 100)。您可以通过
/etc/sysctl.conf
以持久的方式修改它。 (需要重新启动)或以不稳定的方式使用:sysctl vm.swappiness=10
一旦确定存在内存泄漏,就需要获取核心转储并下载以进行分析。可以在另一个 Stackoverflow 响应中找到一种方法:Tools to analyze core dump from Node.js
对于连接泄漏(您通过不处理完成请求而泄漏了连接),您将有越来越多的已建立连接到您的服务器。您可以使用
netstat -a -p tcp | grep ESTABLISHED | wc -l
检查已建立的连接可用于计数已建立的连接。现在,事件循环饥饿 是最糟糕的问题。如果您的代码生命周期很短,则 Node 工作得很好。但是如果你做 CPU 密集型的事情并且有一个功能让 CPU 忙了很长时间......比如 50 毫秒(50 毫秒的稳定、阻塞、同步 CPU 时间,而不是需要 50 毫秒的异步代码),操作是由事件循环处理,例如处理 HTTP 请求开始落后并最终超时。
查找 CPU 瓶颈的方法是使用性能分析器。
nodegrind
/qcachegrind
是我首选的分析工具,但其他人更喜欢火焰图等。然而,在生产中运行分析器可能很困难。只需使用一个开发服务器并用请求猛烈抨击它。又名:负载测试。有很多工具可以做到这一点。最后,另一种调试问题的方法是:
env NODE_DEBUG=tls,net node <...arguments for your app>
Node 具有可选的调试语句,可通过
NODE_DEBUG
启用。环境变量。设置 NODE_DEBUG
至 tls,net
将使 Node 发出 tls 和 net 模块的调试信息......所以基本上所有正在发送或接收的内容。如果有超时,您将看到它的来源。来源:多年维护大型 Node 服务部署的经验。
关于Node.js 服务器超时问题(EC2 + Express + PM2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29812692/