【发布时间】:2020-04-05 07:06:27
【问题描述】:
我们需要导出一个 zip 文件,其中包含大量数据(几 GB)。 zip 存档需要包含大约 50-100 个 indesign 文件(每个大约 100mb)和一些其他较小的文件。我们尝试使用谷歌云功能来实现它(成本更低等)。该功能通过配置文件触发,该文件上传到存储桶中。配置文件包含需要将哪些文件放入 zip 中的所有信息。不幸的是,总是达到 2gb 的内存限制,所以函数永远不会成功。
我们尝试了不同的方法: 第一个解决方案是循环文件,创建下载它们的承诺,在循环完成后,我们尝试一次解决所有承诺。 (文件通过流直接下载到文件中)。 第二次尝试是在 for 循环中等待每次下载,但再次达到内存限制。
所以我的问题是: 为什么node js不清除流?似乎节点将每个流文件保存在内存中并最终崩溃。我已经尝试按照此处的建议将 readStream 和 writeStream 设置为 null:
How to prevent memory leaks in node.js?
但没有变化。
注意:我们从来没有达到这一点,所有文件都被下载以创建 zip 文件。在第一个文件之后它总是失败。
见下方代码sn-ps:
// first try via promises all:
const promises = []
for (const file of files) {
promises.push(downloadIndesignToExternal(file, 'xxx', dir));
}
await Promise.all(promises)
// second try via await every step (not performant in terms of execution time, but we wanted to know if memory limit is also reached:
for (const file of files) {
await downloadIndesignToExternal(file, 'xxx', dir);
}
// code to download indesign file
function downloadIndesignToExternal(activeId, externalId, dir) {
return new Promise((resolve, reject) => {
let readStream = storage.bucket(INDESIGN_BUCKET).file(`${activeId}.indd`).createReadStream()
let writeStream = fs.createWriteStream(`${dir}/${externalId}.indd`);
readStream.pipe(writeStream);
writeStream.on('finish', () => {
resolve();
});
writeStream.on('error', (err) => {
reject('Could not write file');
})
})
}
【问题讨论】:
-
这里的
dir究竟是什么? -
这是一个通过 os.tmpdir() 生成的目录。代码本身可以在我们的开发平台上运行,但只有小文件。在暂存(真实数据)时,我们达到了 2gb 内存限制。
标签: node.js garbage-collection google-cloud-functions google-cloud-storage