上传图片时,Nodejs 内存填得太快了 ~10MB

Dus*_*y48 3 memory memory-leaks image-uploading node.js

概括

通过 JIMP 将图像从 Nodejs 后端上传到 AWS S3 会填满内存堆。

工作流程

  1. 前端(反应)通过表单提交将图像发送到 API
  2. 服务器解析表单数据
  3. JIMP 正在旋转图像
  4. 如果宽度大于 1980 像素,则 JIMP 正在调整图像大小
  5. JIMP 创建缓冲区
  6. 缓冲区正在上传到 S3
  7. Promise 已解决 -> 图像元数据(URL、Bucket 名称、索引等)保存在数据库(MongoDB)中

背景

服务器托管在 Heroku 上,只有 512MB RAM。上传较小的图像和所有其他请求工作正常。但是,当上传一个大于约 8MB 的图像时,应用程序会崩溃,并且只有一个用户在线。

调查至今

我试图在我的本地环境中复制这个。由于我没有内存限制,应用程序不会崩溃,但上传 10MB 图像时内存使用量约为 870MB。一个 6MB 的图像保持在 60MB 左右的 RAM 使用量。我已经更新了所有 npm 包,并尝试禁用对图像的任何处理。

我试图寻找内存泄漏,如下面的屏幕截图所示,但是,对于相同的图像 (6MB) 遵循与上述相同的工作流程,并拍摄 3 个堆快照会产生大约 60MB 的 RAM 使用量。

首先,我认为问题在于图像处理(调整大小)占用了太多内存,但这并不能解释 60MB(对于 6MB 图像)和 10MB 图像大约 800MB 之间的巨大差距。

然后我认为它与“system / JSArrayBufferData”项(见 ref2)有关,它占用了大约 30% 的内存。然而,这个项目总是在那里,即使我不上传图片。它仅在我停止“Chrome 开发工具”下的“内存选项卡”中的录制快照之前出现。但是,我仍然不能 100% 确定它到底是什么。

现在,我相信这与“TimeList”有关(参见 ref3)。我认为它来自等待文件上传到 S3 的超时。但是,在这里,我也绝对不确定为什么会发生这种情况。

以下是我认为在带有 --inspect 标志的 nodejs 服务器上运行的 Chrome Inspector 快照的重要部分的屏幕截图。

Ref1:显示第 3 个快照的完整项目 - 所有 3 个快照都上传了相同的 6MB 图像。由于内存大小没有增加,垃圾似乎已正确收集 Ref2:显示第三个快照的结尾,就在我停止录制之前。不确定“系统/JSArrayBufferData”是什么。 Ref3:显示第 5 个快照的结尾,这是具有 10MB 图像的那个。那些小的、连续的尖峰是“TimeList”项,它似乎与超时有关。当服务器等待来自 AWS 的响应时,它们似乎出现。似乎这也是填满内存的原因,因为上传小于 10MB 的内容时不存在此项目。

Ref4:显示第 5 个快照的立即结束,就在停止录制之前。“system / JSArrayBufferData”再次出现,但是,只出现在最后。

不幸的是,我不知道如何表达我的问题,因为我不知道问题是什么,也不知道我真正需要注意什么。我将非常感谢任何提示或经验。

Dus*_*y48 6

高内存消耗是由包“Jimp”引起的,该包已用于读取文件、旋转文件、调整文件大小并创建缓冲区以上传到文件存储系统。

读取文件的部分,即Jimp.read('filename') 导致了内存问题。这是一个已知的错误,如下所示:https : //github.com/oliver-moran/jimp/issues/153

到现在为止,我已经切换到“锐化”图像处理包,现在可以轻松上传大于 10MB 的图像和视频。

我希望它对遇到这种情况的人也有帮助。

干杯