【问题标题】:Random `ApiError: Invalid Credentials` calling BigQuery from Google Cloud Functions从 Google Cloud Functions 调用 BigQuery 的随机 `ApiError: Invalid Credentials`
【发布时间】:2017-12-31 11:04:00
【问题描述】:

我的函数每小时调用 15 次(每 4 分钟一次),并通过 startQuery 运行查询。大约 30 分钟后随机发生“无效凭据”错误。它发生得越来越频繁,直到所有调用都失败。

此查询从数据集中的表中读取数据,并通过选项destinationwriteDisposition=WRITE_TRUNCATE 将结果保存到位于另一个数据集中的表中。 这两个数据集位于欧盟。

重新部署函数可以暂时消除问题。

gcloud beta functions describe my-function 的调用表明它使用App Engine 默认服务帐户:my-project-id@appspot.gserviceaccount.com

以下是错误详情:

ApiError: Invalid Credentials
at Object.parseHttpRespBody (/user_code/node_modules/@google-cloud/bigquery/node_modules/@google-cloud/common/src/util.js:192:30)
at Object.handleResp (/user_code/node_modules/@google-cloud/bigquery/node_modules/@google-cloud/common/src/util.js:132:18)
at /user_code/node_modules/@google-cloud/bigquery/node_modules/@google-cloud/common/src/util.js:465:12
at Request.onResponse [as _callback] (/user_code/node_modules/@google-cloud/bigquery/node_modules/retry-request/index.js:160:7)
at Request.self.callback (/user_code/node_modules/@google-cloud/bigquery/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/@google-cloud/bigquery/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)

编辑

代码,剥离:

const bigquery = require('@google-cloud/bigquery')();

const destinationDataset = bigquery.dataset('destinationDataset');
const destinationTable = dataset.table('destinationTable');

exports.aggregate = function aggregate (event) {
  const message = event.data;
  const attributes = message.attributes;

  let job;
  let destinationTable;
  return Promise.resolve()
    .then(() => {
      if (attributes.partition == null) {
        throw new Error('Partition time not provided. Make sure you have a "partitionTime" attribute in your message');
      }

      const query = 'SELECT ... FROM sourceTable WHERE _PARTITIONTIME = TIMESTAMP(@partitionTime)'; // The dataset is specified in the job options below

      // Query options list: https://cloud.google.com/bigquery/docs/reference/v2/jobs/query
      // and: https://googlecloudplatform.github.io/google-cloud-node/#/docs/bigquery/0.9.6/bigquery?method=startQuery
      const options = {
        destination: destinationTable,
        writeDisposition: 'WRITE_TRUNCATE',
        query: query,
        defaultDataset: { datasetId: 'sourceDataset' },
        timeoutMs: 540000, // 9 minutes, same timeout as the Cloud Function
        useLegacySql: false,
        parameterMode: 'NAMED',
        queryParameters: [{
          name: 'partitionTime',
          parameterType: { type: 'STRING' },
          parameterValue: { value: attributes.partition }
        }]
      };

      return bigquery.startQuery(options);
    })
    .then((results) => {
      job = results[0];
      console.log(`BigQuery job ${job.id} started, generating data in ${destinationTable.dataset.id}.${destinationTable.id}.`);
      return job.promise();
    })
    .then((results) => {
      // Get the job's status
      return job.getMetadata();
    })
    .then((metadata) => {
      // Check the job's status for errors
      const errors = metadata[0].status.errors;
      if (errors && errors.length > 0) {
        throw errors;
      }
    })
    // Only if a destination table is given
    .then(() => {
      console.log(`BigQuery job ${job.id} completed, data generated in ${destinationTable.dataset.id}.${destinationTable.id}.`);
    })
    .catch((err) => {
      console.log(`Job failed for ${inspect(attributes)}: ${inspect(err)}`);
      return Promise.reject(err);
    });
};

您会注意到在初始化 bigquery 对象时我没有提供任何选项:require('@google-cloud/bigquery')()

我是否应该创建一个角色为 BigQuery 作业用户use the RuntimeConfig API 的服务帐户,以避免将凭据推送到 git 源?

问题仍然是为什么我随机收到此错误。现在查看函数日志,在 CEST 午夜到凌晨 4 点之间的每个调用中都发生了错误,然后在凌晨 5:36 之前的三分之一调用中发生了错误。从那时起(4 小时前)它就没有发生过一次。

编辑 2

这显示了失败调用与成功调用相比的频率。所有错误(绿色)都是“Invalid Credentials”错误。在这 7 天里,绝对没有任何事情发生:没有部署,没有更改配置,没有在 BigQuery 中摆弄。

【问题讨论】:

  • 你能给我们看看你的代码示例吗?
  • 完成。添加了一个编辑部分。
  • 遇到同样的问题;我有一个云函数,它从新的云存储上传(每 1 分钟发生一次)得到通知,并且该函数每 1 分钟调用一次,它只是调用 bigquery 将其加载到表中,这个函数是在两周前运行的直到今天都没有问题 ApiError 在几分钟内随机发生,并非总是如此;这一定是谷歌方面的操作问题

标签: google-bigquery google-cloud-functions google-api-nodejs-client


【解决方案1】:

我的解决方法是使用 GCE 中的 VM 并运行 nodejs 应用程序来包装函数,例如

const pubsub = require('@google-cloud/pubsub')();
const topic = pubsub.topic('...');
const sub = topic.subscribe('...', { ...options });
sub.on('message', msg => {
   // the same cloud function does all bigquery data loading and querying stuff...
   callthesamecloudfunction({ data: msg });
});

取决于 GCF 中使用哪种触发器,包装器可能不同;

好的方面是包装器足够简单,它已经在我们的生产环境中运行了几个月,没有任何问题;

我的结论是 GCloud 在 Beta 中运行许多服务,并没有真正为生产做好准备;我会远离 GCF,或者可能会在 6 个月后重新访问。

编辑:请参阅https://issuetracker.google.com/issues/66695033 GCloud 团队声称已修复但我还没有时间测试;我的包装方式只需要一个云虚拟机,而且非常便宜。

【讨论】:

    猜你喜欢
    • 2019-03-25
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 2018-07-21
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多