Node.js 服务器超时问题(EC2 + Express + PM2)

2023-11-21

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

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

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

关于可能发生的情况以及如何解决这个问题有任何线索吗?

这是我的堆栈:

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

再次,上述任何模块都没有发生错误。


首先,您需要对超时有更具体的了解。

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

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

现在,造成这种情况的可能原因有很多很多……从更微不足道到不那么微不足道:

  • 内容长度计算错误:如果您发送带有Content-Length: 20header,这意味着“我要向你发送 20 个字节”。如果您发送 19 个,另一端将等待剩余的 1 个。如果花费的时间太长...超时。

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

  • 无声异常:抛出了一个错误,但没有记录在任何地方。该请求从未完成处理,导致下一个项目。

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

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


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

更糟糕的是,如果可用内存较低并且您的服务器错误配置为使用交换,Linux 将开始将内存移动到磁盘(交换),这是 I/O 和 CPU 密集型的。服务器不应启用交换。

cat /proc/sys/vm/swappiness

将返回您系统中配置的交换级别(从 0 到 100)。您可以通过以下方式以持久方式修改它/etc/sysctl.conf(需要重新启动)或以不稳定的方式使用:sysctl vm.swappiness=10

一旦确定存在内存泄漏,您需要获取核心转储并下载它以进行分析。可以在另一个 Stackoverflow 响应中找到一种方法:用于分析 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_DEBUG环境变量。环境NODE_DEBUG to tls,net将使节点发出 tls 和 net 模块的调试信息...所以基本上所有内容都被发送或接收。如果出现超时,您将看到它来自哪里。

Source:拥有多年维护节点服务大型部署的经验。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node.js 服务器超时问题(EC2 + Express + PM2) 的相关文章

随机推荐

  • 创建StanfordCoreNLP对象时出错

    我已经从以下位置下载并安装了所需的 jar 文件http nlp stanford edu software corenlp shtml Download 我已经包含了五个 jar 文件 斯坦福 pos tagger jar 斯坦福 pso
  • ANDROID_LOOP = true -- 如何避免 MediaPlayer 使用此元数据标签循环音频

    我想用 MediaPlayer 播放设备铃声 但似乎元数据标签 ANDROID LOOP true 设置MediaPlayer忽略该方法的调用设置循环 mMediaPlayer setLooping false 并在任何情况下循环播放音频
  • Python PIPE 到 popen stdin

    我正在尝试类似的事情实时 subprocess Popen 通过 stdout 和 PIPE 但是 我也想将输入发送到正在运行的进程 如果我使用以下命令在单独的线程中启动进程 process subprocess Popen cmd std
  • 比较时,不带键字段的 VB.NET 匿名类型与 C# 匿名类型有何不同?

    我对此感到摸不着头脑 因为我无法理解为什么会发生以下情况 VB NET Dim product1 New With Name paperclips Price 1 29 Dim product2 New With Name papercli
  • npm 安装失败

    首先我要说的是 我几乎没有在终端或使用 Node js 工作的经验 同事去度假了 我正在尝试按照他留下的说明在我们的演示服务器上设置他的应用程序 我可以让所有内容在本地运行 但在安装 socket io 模块的服务器上遇到问题 安装了pyt
  • 产品平面表不会重新索引 - 行大小太大

    当我尝试重新索引产品平面数据时 我得到There was a problem with reindexing process 数据库修复没有帮助 Exception log 文件显示此错误 2011 08 29T11 54 05 00 00
  • IE 10 中的 event.preventDefault

    我正在提交一个表单 并且我想阻止提交操作 直到我执行一些其他操作 例如显示文件上传进度条 我根据诸如此类的问题设置了此代码event preventDefault 函数在 IE 中不起作用 document ready function f
  • 如何在 Twig 日期过滤器中使用时区?

    我正在使用 Twig 和这个日期过滤器 http www twig project org doc templates html date 显然他们正在寻找参数中的 DateTime 实例 看着这个http www php net manu
  • 提要对话框:图片未显示

    我的 Facebook 提要对话框链接正确呈现了对话框页面 但使用图片参数设置的图像未显示 只是表示没有图片的灰线 我已经更改了图片文件和类型几次 但图像仍然不显示 这是代码 share url https www facebook com
  • Python的打印函数在调用时会刷新缓冲区? [复制]

    这个问题在这里已经有答案了 我有以下代码来刷新输出缓冲区 print return 1 sys stdout flush 我可以设置打印函数 以便它在调用时自动刷新缓冲区吗 您可以使用 u 标志以无缓冲模式启动 python 例如 pyth
  • java.lang.NoSuchMethodError: org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont.addNewFamily()

    将 poi 升级到版本并添加来自 apache 站点的 jar 包 但是出现以下错误 java lang NoSuchMethodError org openxmlformats schemas spreadsheetml x2006 ma
  • 将查询字符串解析为数组

    我怎样才能转一个string下面进入array pg id 2 parent id 2 document video 这就是我正在寻找的数组 array pg id gt 2 parent id gt 2 document gt video
  • 泛型函数类型别名

    为什么在 TypeScript 中类型别名不能与泛型函数一起使用 例如 这里 TS 没有将 Identical 类型定义为泛型 type Identical
  • Django ALLOWED_HOSTS 通过 Apache 接受本地 IP

    我正在使用 Apache 提供 Django 应用程序 在 Django 的 settings py 中我有DEBUG False 因此我必须允许一些主机 例如 ALLOWED HOSTS dyndns org localhost 这工作正
  • Keras 自定义损失作为多个输出的函数

    我使用 keras 一个卷积网络 构建了一个自定义架构 该网络有 4 个头 每个头输出不同大小的张量 我正在尝试编写一个自定义损失函数作为这 4 个输出的函数 我之前一直在实施自定义损失 但它要么是每个头的不同损失 要么是每个头的相同损失
  • 在“DELETE FROM table”之后更改 sqlite 文件大小

    我正在使用 sqlite3 文件 首先 我进入了比较大的数据库 文件大小约为100 MB 比我做的 db gt exec DELETE FROM table 并只输入了该数据库的一小部分 但文件大小仍为 100 MB 删除 sqlite 文
  • Android:从回调中获取结果(网络 KOUSH ION)

    对于我的应用程序 我需要从我们的服务器联系我们的 API 该服务器返回一些 JSON 下载 JSON 时 它应该显示一个进度条 我想我应该使用Android的AsyncTask在进行网络操作时处理 GUI 所以我在我的文件中编写了以下内容A
  • 如何最好地处理 C/C++ 中的动态多维数组?

    在 C 和 或 C 中操作动态 所有维度直到运行时才知道 多维数组的可接受 最常用的方法是什么 我正在尝试找到最简洁的方法来完成此 Java 代码的功能 public static void main String args Scanner
  • std::move 和 RVO 优化

    我最近读过如何std move可以通过仅移动值而不是复制它们来加速代码 所以我做了一个测试程序来比较速度std vector 代码 include
  • Node.js 服务器超时问题(EC2 + Express + PM2)

    我对运行生产 Node js 应用程序还比较陌生 最近我遇到了服务器超时的问题 基本上在一定的使用量和时间后 我的 Node js 应用程序停止响应请求 我什至不再看到在我的控制台上触发路由 就好像整个事情都停止了 来自我的客户端 运行 A