Firebase 云功能 [错误:超出内存限制。函数调用被中断。] 在 youtube 视频上传
Posted
技术标签:
【中文标题】Firebase 云功能 [错误:超出内存限制。函数调用被中断。] 在 youtube 视频上传【英文标题】:Firebase cloud function [ Error: memory limit exceeded. Function invocation was interrupted.] on youtube video upload 【发布时间】:2019-04-16 12:39:22 【问题描述】:我正在尝试使用 firebase 云功能将视频上传到 youtube。
我需要的是当用户将视频上传到 firebase 云存储时,functions.storage.object().onFinalize 事件将被触发,在这种情况下,我将文件存储到临时位置并将文件上传到 youtube从临时位置到 youtube,上传后我删除了这两个文件。
它适用于小文件。
但是如果我上传一个大文件,那么函数会因为显示这个错误而终止
错误:超出内存限制。函数调用被中断。
上传视频的代码
var requestData =
'params':
'part': 'snippet,status'
,
'properties':
'snippet.categoryId': '22',
'snippet.defaultLanguage': '',
'snippet.description': "docdata.shortDesc",
'snippet.tags[]': '',
'snippet.title': "docdata.title",
'status.embeddable': '',
'status.license': '',
'status.privacyStatus': 'public',
'status.publicStatsViewable': ''
, 'mediaFilename': tempLocalFile
;
insertVideo(tempLocalFile, oauth2Client, requestData);
插入视频功能
function insertVideo( file, oauth2Client, requestData)
return new Promise((resolve,reject)=>
google.options( auth: oauth2Client );
var parameters = removeEmptyParameters(requestData['params']);
parameters['auth'] = oauth2Client;
parameters['media'] = body: fs.createReadStream(requestData['mediaFilename']);
parameters['notifySubscribers'] = false;
parameters['resource'] = createResource(requestData['properties']);
console.log("INSERT >>> ");
let req = google.youtube('v3').videos.insert(parameters, (error, received)=>
if (error)
console.log("in error")
console.log(error);
try
fs.unlinkSync(file);
catch (err)
console.log(err);
finally
// response.status(200).send( error: error )
reject(error)
else
console.log("in else")
console.log(received.data)
fs.unlinkSync(file);
resolve();
);
)
创建临时本地文件的代码
bucket.file(filePath).createReadStream()
.on('error', (err)=>
reject(err)
)
.on('response', (response)=>
console.log(response)
)
.on('end', ()=>
console.log("The file is fully downloaded");
resolve();
)
.pipe(fs.createWriteStream(tempLocalFile));
每个文件的读取和写入都由流处理,不知道为什么会发生内存问题
【问题讨论】:
Hey Suhail,想知道如果您使用云功能来处理事件,您是如何设置 oauth2Client 的。您如何获得浏览器访问权限以建立 OAuth?谢谢!!! 我使用了 oauth 操场,developers.google.com/oauthplayground 太酷了!我会看看。顺便说一句,生成令牌后,您将其放在服务器的哪个位置以便云功能可以访问它?非常感谢! 添加到配置中 抱歉 Suhail,你能说得更具体点吗?真的很抱歉我是这个云功能的新手????。配置在哪里?是火力基地吗? 【参考方案1】:最简单的快速修复是increase function memory
对于 Firebase,docs 告诉您像这样设置函数内存:
exports.convertLargeFile = functions
.runWith(
timeoutSeconds: 300,
memory: '1GB',
)
.storage.object()
.onFinalize((object) =>
// Do some complicated things that take a lot of memory and time
);
内存的有效值为 128MB 256MB 512MB 1GB 2GB 4GB 8GB
但是,单独设置它对我不起作用。我还得去Google Cloud Platform Console functions list
然后单击要增加其内存的函数的名称。这将带您进入编辑屏幕,您可以在其中进行更改并部署更改。这只是单击按钮和更改下拉值的问题。
完成后,您应该会在上述函数列表和 firebase 函数列表中看到更改 - https://console.firebase.google.com/u/0/project/YOUR_PROJECT/functions/list
现在你的函数应该可以工作了!来自 J-E-S-U-S my Lord 的爱。
【讨论】:
【参考方案2】:您也可以按照一系列步骤使用resumable video upload:
-
当视频完成上传时,您的 GCS 触发函数会被触发。
该函数启动一个resumable upload session,计算什么是合理的块上传,并将块定义插入到pubsub,每个块的范围和会话ID
您使用接收该消息的主题创建一个新的 pubsub-triggered 函数,使用
range
标头从 GCS 下载块(在 JSON API 上未记录,但我已经报告了它)和 uploads the chunk to Youtube
我没有尝试过,但这甚至可能允许从上传不同块的不同函数并行上传到 Youtube(这将大大提高性能,尽管文档建议需要按顺序上传块)。您可以从 GCS 对象下载任意块,因此 GCS 方面对于并行化来说不是问题。
如果不允许并行上传,您可以在函数完成上传带有最后一个字节的块上传时插入新的 pubsub 消息,因此函数的执行是有序的(同时它允许并行上传不同的视频)。
这有点复杂,但允许您从小功能上传任意大小的视频(YouTube 上当前的 128 GB 限制)。
注意正确处理故障(也许将块重新插入到 pubsub 主题中)。
【讨论】:
【参考方案3】:Cloud Functions 中文件系统的唯一可写部分是 /tmp
目录。根据文档here:
这是一个本地磁盘挂载点,称为“tmpfs”卷,其中 写入卷的数据存储在内存中。请注意,它将 消耗为函数配置的内存资源。
这就是您使用更大的文件达到内存限制的原因。
您的选择是:
为您的函数分配更多内存(目前最多 2 GB) 从可以写入文件系统的环境中执行上传。例如,您的 Cloud Function 可以调用 App Engine Flexible 服务来执行上传。【讨论】:
以上是关于Firebase 云功能 [错误:超出内存限制。函数调用被中断。] 在 youtube 视频上传的主要内容,如果未能解决你的问题,请参考以下文章
Firebase Cloud Functions 部署错误 - 超出配额
使用 Firebase 云功能时出现 Stackdriver 错误“未配置结算帐户”
如何限制 Firebase 云功能仅接受来自 Firebase 托管网站的请求