随机`ApiError:无效凭据`从Google Cloud Functions调用BigQuery

时间:2017-07-25 13:22:46

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

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

此查询从数据集中的表中读取数据,并通过选项SELECT t1.name, t2.login AS added_by, t3.login AS edited_by FROM table1 t1 INNER JOIN table2 t2 ON(t1.added_by=t2.id) INNER JOIN table2 t3 ON(t1.edited_by=t3.id) destination将结果保存到位于其他数据集中的表中。 这两个数据集位于欧盟。

重新部署该功能会暂时消除此问题。

writeDisposition=WRITE_TRUNCATE的调用表明它使用的是App Engine默认服务帐户:gcloud beta functions describe my-function

以下是错误详情:

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)

你会注意到我在初始化bigquery对象时没有给出任何选项: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 Job User 的服务帐户,以及use the RuntimeConfig API以避免将凭据推送到git源吗?

问题仍然存在,为什么我会随机收到此错误。现在查看功能日志,错误发生在午夜和凌晨4点CEST之间的每次通话,然后是三分之一的通话,直到凌晨5:36。从那时起(4小时前),它没有发生过一次。

修改2

这显示了与成功调用相比失败调用的频率。所有错误(绿色)都是“Invalid Credentials”错误。在这7天中绝对没有触及任何内容:没有部署,没有配置更改,没有BigQuery中的小提琴。

frequency of credentials errors

1 个答案:

答案 0 :(得分: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团队声称已修复,但我还没有时间进行测试;我的封装方式只花费一个云虚拟机并且非常便宜。