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)

如何通过Google Cloud调试在Docker容器内运行的Nodejs应用程序

Cloud Function 将功能部署到所选项目

如何通过 Cloud Build 访问 GSM 机密并传递给 Cloud Function