Cloud Function 运行缓慢并超出可用内存
Posted
技术标签:
【中文标题】Cloud Function 运行缓慢并超出可用内存【英文标题】:Cloud Function runs slowly and exceeds available memory 【发布时间】:2021-12-07 02:12:37 【问题描述】:我正在使用 Cloud Functions 跨 BigQuery 中的分区表运行查询。该表大小为 1GB。
该脚本会提取所有匹配 id 的数据并将每个数据流式传输到 Google Cloud Storage 存储桶中。它对表中的所有 id 执行此操作(大约 100 次)。该脚本正在运行,但它运行缓慢,并且在 Cloud Function 内存不足之前仅拉出 9 个商家。在构建菜单中增加内存没有任何效果。
有没有办法加快这个操作并减少它每次使用的内存量?
const BigQuery = require("@google-cloud/bigquery");
const Storage = require("@google-cloud/storage");
const bucketName = "xxxx";
const stream = require("stream");
const parse, Parser = require("json2csv");
const bigquery = new BigQuery();
const storage = new Storage();
const fields = [
"id",
"product_name",
"product_desc",
"etc"
];
exports.importBQToGCS = (req, res) =>
"use strict";
const liveMerchantCount = 113;
(async function ()
try
for (let i = 1; i < liveMerchantCount; i += 1)
const query =
`SELECT *
FROM \`table_name\`
WHERE id_number = ` + i;
const options =
query: query,
location: "EU",
;
const [job] = await bigquery.createQueryJob(options);
console.log(`Job $job.id started.`);
const createFile = storage.bucket(bucketName).file(`test_$i.csv`);
const [rows] = await job.getQueryResults();
const csv = parse(rows, fields );
const dataStream = new stream.PassThrough();
dataStream.push(csv);
dataStream.push(null);
await new Promise((resolve, reject) =>
console.log("Writing to GCS");
dataStream
.pipe(
createFile.createWriteStream(
resumable: false,
validation: false,
metadata: "Cache-Control": "public, max-age=31536000" ,
)
)
.on("error", (error) =>
console.error("Stream failed", error);
reject(error);
)
.on("finish", () =>
resolve(true);
);
);
res.status(200).send();
catch (err)
res.send(err);
)();
;
【问题讨论】:
你的云功能配置是什么? 内存设置为 8GB(最大可用),最大实例 3,000,300 秒超时和节点版本 14 【参考方案1】:您可以通过从 BigQuery 流式传输记录来减少内存占用。如果您使用@databases 客户端,它有一个queryNodeStream
方法正好适用于这个用例:https://www.atdatabases.org/docs/bigquery-client#bigqueryclient-querynodestream
const connectBigQuery, sql = require("@databases/bigquery");
const Storage = require("@google-cloud/storage");
const bucketName = "xxxx";
const stream = require("stream");
const parse, Parser = require("json2csv");
const bigquery = connectBigQuery();
const storage = new Storage();
const fields = [
"id",
"product_name",
"product_desc",
"etc"
];
exports.importBQToGCS = (req, res) =>
"use strict";
const liveMerchantCount = 113;
(async function ()
try
for (let i = 1; i < liveMerchantCount; i += 1)
await new Promise((resolve, reject) =>
console.log("Writing to GCS");
bigquery.queryNodeStream(sql`
SELECT * FROM table_name WHERE id_number = $i
`)
.on('error', reject)
.pipe(someStreamingCsvLibrary( fields ))
.on('error', reject)
.pipe(
createFile.createWriteStream(
resumable: false,
validation: false,
metadata: "Cache-Control": "public, max-age=31536000" ,
)
)
.on("error", (error) =>
console.error("Stream failed", error);
reject(error);
)
.on("finish", () =>
resolve(true);
);
);
res.status(200).send();
catch (err)
res.send(err);
)();
;
【讨论】:
【参考方案2】:在进一步测试中,问题似乎是 BigQuery 正在为一个正在为此函数清除内存的商家返回一个特别大的 JSON 文件 (250MB)。所有其他的都低于 100MB。一旦我排除了这个特定的查询,该函数就会按预期工作。
【讨论】:
以上是关于Cloud Function 运行缓慢并超出可用内存的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Cloud Function 获取 Firebase 项目名称或 ID
从 App Engine 运行时 Python 3.7 调用 Cloud Function [重复]
Firebase Firestore + Cloud Function 服务器端验证应用内购买收据(Swift + NodeJS)