【问题标题】:Firebase Functions - ERROR, but no Event Message in ConsoleFirebase 函数 - 错误,但控制台中没有事件消息
【发布时间】:2018-08-28 17:50:01
【问题描述】:

我在 firebase 上编写了一个函数,它从 firebase 存储下载图像(base64)并将其作为响应发送给用户:

const functions = require('firebase-functions');
import os from 'os';
import path from 'path';
const storage = require('firebase-admin').storage().bucket();

export default functions.https.onRequest((req, res) => {
    const name = req.query.name;

    let destination = path.join(os.tmpdir(), 'image-randomNumber');
    return storage.file('postPictures/' + name).download({
        destination
    }).then(() => {
        res.set({
            'Content-Type': 'image/jpeg'
        });
        return res.status(200).sendFile(destination);
    });
});

我的客户多次之后调用该函数(串联)以加载一系列图像以供显示,ca。 20 个,平均大小为 4KB。

在加载了 10 张左右的图片(数量不同)后,所有其他图片都失败了。原因是我的函数没有正确响应,firebase 控制台显示我的函数抛出了错误:

上图显示

  1. 对函数(称为“PostPictureView”)的请求成功
  2. 之后,对控制器的三个请求失败
  3. 最后,在对“UserLogin”函数执行新请求后,同样失败。

给客户端的响应是默认的“错误:无法处理请求”。等待几秒钟后,所有请求都会再次按原样处理。

我的最佳猜测:

  • 该项目处于免费层,也许谷歌正在限制某些东西? (我没有达到任何限制)
  • Google Firebase 控制台可以处理的消息是否有限制?
  • functions-app 中的 tmpdir 是否运行不足?到目前为止,我从未删除过临时文件,但希望谷歌会自动删除它们,或者以不同的方式警告我空间不足。

是否有人知道接收错误消息的替代方法,或者遇到过类似的问题? (由于 Firebase Functions 仍处于测试阶段,也可能是来自 google 的错误)

顺便说一句:直接从客户端(android app,react-native)下载图像是不可能的,因为我稍后会使用该功能检查访问权限。这个问题对我来说是可重现的。

【问题讨论】:

  • image-randomNumber 是您正在下载的文件的字面名称,还是实际上包含一些随机数?
  • 不,它实际上包含一个随机字符串:let destination = path.join(os.tmpdir(), 'image-' + Math.random().toString(36).substring(7)); 只是为了便于阅读在上面进行了简化。

标签: node.js firebase google-cloud-functions firebase-storage


【解决方案1】:

经过更多研究,我找到了解决方案:Firebase 控制台似乎没有显示所有错误信息。

有关您的函数的详细信息以及 Firebase 控制台中可能忽略的错误,请查看website from google cloud functions

我看到:内存(如@Doug Stevensson 所建议的)使用从未超过 80MB(限制为 256MB)并且从未关闭服务器。此外,我的应用程序遇到了免费层的 DNS 解析限制。

documentation 指向DNS resolutions: 40,000 per 100 seconds 的限制。就我而言,这个限制从未达到过——firebase 计算的总执行次数约为 8000 次——但似乎免费层有一个较低的、未记录的限制。升级我的帐户(我开始了 GCP 提供的试用版,因此实际上没有支付任何费用)并将项目链接到结算帐户后,一切正常。

【讨论】:

  • 您显示的代码不应该导致关于免费层限制的错误,因为您实际上没有使用任何外部 API。
  • 我添加了一个截图。随着时间戳和函数名称的匹配,我想这至少是问题的一部分——尽管我在documentation 中发现只有DNS resolutions: 40,000 per 100 seconds 的限制,这绝对没有被命中(今天的所有请求和昨天加起来大约是 8000),但是也许免费层有一个未记录的下限以防止滥用?我想我会在升级后知道更多。
【解决方案2】:

在 Cloud Functions 中,/tmp 目录为 backed by memory。因此,您在那里下载的每个文件都会有效地占用运行该函数的服务器实例上的内存。

Cloud Functions 可能会重复使用服务器实例来重复调用同一函数。这意味着您的函数在每次调用时都会下载另一个文件(到同一个实例)。由于文件名每次都不一样,所以你是在 /tmp 中累积文件,每个文件都占用内存。

在某些时候,该服务器实例的内存将因 /tmp 中的所有这些文件而耗尽。这很糟糕。

always clean up files after you're done with them 是最佳做法。更好的是,如果您可以将文件内容从 Cloud Storage 流式传输到客户端,您将使用更少的内存 (and be billed even less for the memory-hours you use)。

【讨论】:

  • 我试过删除这些文件,但似乎它们被自动删除了。在sendFile 之后我尝试过:return fs.unlinkSync(destination); => "ENOENT: no such file or directory, stat '/tmp/image-v944xyv9uj0rvcqmpldi'" 我会做一些研究并尝试将文件内容直接流式传输到客户端,但似乎该函数没有直接耗尽内存。如果您有任何链接或一段工作代码,那将非常有帮助 - 在运行存储时遇到了一些问题。
  • 它们不会被自动删除。您需要删除单个文件,而不是尝试删除所有 /tmp。 cloud.google.com/functions/docs/bestpractices/…
  • 刚刚注意到上面注释代码中的一个小错误,我会重试。
  • 执行fs.readdirSync(os.tmpdir()) 总是会给我一个包含 1 个文件的数组,如果我尝试在下一个代码行中删除该文件,我会收到一个 ENOENT: no such file or directory, open '/tmp/image-f6b6mo69ye2e7t84obt9'
  • 不知道该告诉你什么。没遇到过这个问题,官方函数示例代码全部删除tmp文件。
猜你喜欢
  • 2012-02-14
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 2013-06-07
  • 2015-02-05
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多