Cloud Functions for Firebase 由于超出内存限制而终止

Cloud Functions for Firebase killed due to memory limit exceeded

在转换相对较小的图像 (2mb) 时,我不断收到来自 Cloud Functions for Firebase 的偶发错误。成功时,该功能仅需大约 2000 毫秒或更短时间即可完成,根据 Image Magick 文档,我应该不会发现任何问题。

我尝试增加命令的缓冲区大小,这在 Firebase 中是不允许的,我试图找到 .spawn() 的替代方法,因为它可能会因垃圾而超载并减慢速度。没有任何效果。

[更新] 正如一位评论者所建议的那样,这应该不再是一个问题,因为 firebase 函数现在在重新部署时会保持其设置。感谢 firebase!

事实证明,这并不明显或没有记录,您可以在 Google Functions Console 中增加对函数的内存分配。您还可以增加 long-运行 函数的超时时间。它解决了内存过载的问题,现在一切正常。

编辑:请注意,Firebase 会在部署时重置您的默认值,因此您应该记得登录到控制台并立即更新它们。我仍在寻找通过 CLI 更新这些设置的方法,找到后会更新。

更新:看起来他们现在可以在重新部署时保留设置,因此您可以安全地更改云控制台中的内存分配!

我在UI迷路了,找不到任何更改内存的选项,但终于找到了:

  1. 转到 Google 云平台控制台(不是 Firebase 控制台)
  2. Select Cloud Functions 在菜单中
  3. 现在你会在这里看到你的 firebase 函数,如果它是正确的话。否则检查您是否选择了正确的项目。
  4. 忽略所有复选框、按钮和菜单项,只需单击函数名称
  5. 点击编辑(顶部菜单),仅更改分配的内存并点击保存。

Firebase Cloud Functions 中的默认 ImageMagick 资源配置似乎与分配给函数的实际内存不匹配。

运行 identify -list resource 在 Firebase 云函数的上下文中产生:

File       Area         Memory        Map       Disk   Thread  Throttle       Time
--------------------------------------------------------------------------------
 18750    4.295GB       2GiB       4GiB  unlimited        8         0   unlimited  

分配给 FCF 的默认内存是 256MB - 默认的 ImageMagick 实例认为它有 2GB,因此不会从磁盘分配缓冲区,并且很容易尝试过度分配内存导致函数在 Error: memory limit exceeded. Function killed.

一种方法是按照上面的建议增加所需的内存 - 尽管仍然存在 IM 会根据您的用例和异常值尝试过度分配的风险。

更安全的方法是使用 -limit memory [your limit] 将正确的内存限制设置为 IM 作为图像处理过程的一部分。你可以通过 运行 你的 IM 逻辑和 `-debug Cache' 计算出你的大约内存使用量 - 它会告诉你所有分配的缓冲区,它们的大小以及它们是内存还是磁盘。

如果 IM 达到内存限制,它将开始在磁盘上分配缓冲区(内存映射,然后是常规磁盘 buffers.You 必须考虑 I/O 性能与内存成本之间的具体平衡。价格您分配给 FCF 的每一个额外内存字节的使用量都会乘以 100 毫秒 - 因此可以快速增长。

这里的另一种选择是完全避免使用 .spawn()

有一个很棒的节点图像处理包叫做 Sharp that uses the low-memory footprint library libvips. You can check out the Cloud Function sample on Github

或者,ImageMagick(和 GraphicsMagick)的节点包装器称为 gm. It even supports the -limit 选项,用于向 IM 报告您的资源限制。

最新的 firebase 部署命令确实将内存分配覆盖为默认的 256MB,超时时间长达 60 秒。

或者,要指定所需的内存分配和最大超时,我使用 gcloud 命令,例如:

gcloud beta functions deploy YourFunctionName --memory=2048MB --timeout=540s

其他选项,请参考:

https://cloud.google.com/sdk/gcloud/reference/beta/functions/deploy

您可以在 Firebase 上的 Cloud Function 文件中进行设置。

const runtimeOpts = {
  timeoutSeconds: 300,
  memory: '1GB'
}

exports.myStorageFunction = functions
  .runWith(runtimeOpts)
  .storage
  .object()
  .onFinalize((object) = > {
    // do some complicated things that take a lot of memory and time
  });

摘自此处的文档: https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation

别忘了从您的终端 运行 firebase deploy

你可以在这里调整你的记忆:

您可以在您的 firebase 函数定义中添加配置,例如:

functions.runWith({memory: '2GB', timeoutSeconds: '360'})

从 UI 中找出答案有点棘手,所以这里有一些引导性的屏幕截图:
转到 url https://console.cloud.google.com/functions/list


您还可以增加 60 秒的默认超时