【问题标题】:Node.js Server Timeout Problems (EC2 + Express + PM2)Node.js 服务器超时问题(EC2 + Express + PM2)
【发布时间】:2015-07-01 00:05:37
【问题描述】:

我对运行生产 node.js 应用程序比较陌生,最近我遇到了服务器超时问题。

基本上在一定数量的使用和时间之后,我的 node.js 应用程序停止响应请求。我什至看不到在我的控制台上触发路由 - 就像整个事情刚刚停止,来自我的客户端(运行 AFNetworking 的 iPhone)的 HTTP 调用不再到达服务器。但是,如果我重新启动我的 node.js 应用程序服务器,一切都会重新开始工作,直到事情不可避免地再次停止。应用永远不会崩溃,它只是停止响应请求。

我没有收到任何错误,而且我已确保处理并记录所有数据库连接错误,所以我不确定从哪里开始。我认为这可能与内存泄漏有关,因此我安装了 node-memwatch 并设置了内存泄漏监听器,但在我的服务器停止响应请求之前不会调用它。

关于可能发生的事情以及如何解决此问题的任何线索?

这是我的堆栈:

  • AWS EC2 微型实例上的 Node.js(使用 Express 4.0 + PM2)
  • 运行 MySQL 的 AWS RDS 卷上的数据库(使用 node-mysql)
  • 使用 Redis 将会话存储在与 node.js 应用程序相同的 EC2 实例上
  • 客户端是通过 AFNetworking 访问服务器的 iPhone

再一次,上面提到的任何模块都没有触发错误。

【问题讨论】:

  • 听起来好像您的某些路由没有返回响应,因此挂起其他所有内容

标签: node.js http express amazon-ec2 connection-timeout


【解决方案1】:

首先,您需要更具体地了解超时。

  • TCP 超时:TCP 将消息分成数据包,然后一一发送。接收方需要确认已收到数据包。如果接收方在一定时间内没有确认收到包,则会发生 TCP 重传,即再次发送相同的包。如果这种情况再发生几次,发送方就会放弃并终止连接。

  • HTTP 超时:HTTP 客户端(如浏览器)或您的服务器充当客户端(例如:向其他 HTTP 服务器发送请求)可以设置任意超时。如果在这段时间内没有收到响应,它将断开连接并称之为超时。

现在,有很多很多可能的原因......从更微不足道到不太微不足道:

  • 错误的 Content-Length 计算:如果您发送带有 Content-Length: 20 标头的请求,则表示“我将向您发送 20 个字节”。如果您发送 19,另一端将等待剩余的 1。如果时间太长...超时。

  • 基础设施不足:也许您应该为您的应用程序分配更多机器。如果(total load / # of CPU cores) 大于 1,或者您的内存使用率很高,则您的系统可能已超出容量。但是请继续阅读...

  • 静默异常:引发错误但未在任何地方记录。请求从未完成处理,导致下一个项目。

  • 资源泄漏:每个请求都需要处理完成。如果您不这样做,连接将保持打开状态。此外,IncomingMesage 对象(又名:在 express 代码中通常称为req)将保持被其他对象引用(例如:express 本身)。这些对象中的每一个都可以使用大量内存。

  • 节点事件循环饥饿:我会在最后讲到。


对于内存泄漏,症状是: 节点进程将使用越来越多的内存。

更糟糕的是,如果可用内存不足,并且您的服务器被错误配置为使用交换,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 检查已建立的连接,可用于计算已建立的连接。

现在,事件循环饥饿是最严重的问题。如果你有短暂的代码节点工作得很好。但是,如果你做 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 将使节点发出 tls 和 net 模块的调试信息......所以基本上所有被发送或接收的东西。如果有超时,你会看到它来自哪里。

来源:多年维护大型节点服务部署的经验。

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 2019-03-15
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 2018-12-28
    • 2015-08-17
    相关资源
    最近更新 更多