首页 > 解决方案 > 上传图片时,Nodejs 内存填得太快了 ~10MB

问题描述

概括

通过 JIMP 从 Nodejs 后端将图像上传到 AWS S3 会占用大量内存。

工作流程

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

背景

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

调查至今

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

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

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

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

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

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

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

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

问题

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

标签: node.jsmemorymemory-leaksimage-uploading

解决方案


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

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

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

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

干杯


推荐阅读