Random `ApiError: Invalid Credentials` calling BigQuery from Google Cloud Functions
我的函数每小时调用 15 次(每 4 分钟一次),并通过 startQuery 运行查询。大约 30 分钟后随机发生"无效凭据"错误。它发生得越来越频繁,直到所有调用都失败。
此查询从数据集中的表中读取数据,并通过选项
这两个数据集位于欧盟。
重新部署该功能可暂时消除问题。
对
以下是错误详情:
1 2 3 4 5 6 7 8 9 10 11 | 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. (/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) |
编辑
代码,剥离:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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 对象时没有给出任何选项:
我是否应该创建一个角色为 BigQuery 作业用户的服务帐户,并使用 RuntimeConfig API 来避免将凭据推送到 git 源?
问题仍然是为什么我会随机收到此错误。现在查看函数日志,在 CEST 午夜到凌晨 4 点之间的每个调用中都发生了错误,然后在凌晨 5:36 之前的三分之一调用中发生了错误。从那时起(4 小时前)它就没有发生过一次。
编辑 2
这显示了失败调用与成功调用相比的频率。所有错误(绿色)都是"无效凭据"错误。在这 7 天里,绝对没有任何事情发生:没有部署、没有更改配置、没有在 BigQuery 中摆弄。
我的解决方法是使用 GCE 中的 VM 并运行 nodejs 应用程序来package函数,例如
1 2 3 4 5 6 7 | 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 中使用哪种触发器,package器可能不同;
好的方面是package器足够简单,它已经在我们的生产环境中运行了几个月,没有任何问题;
我的结论是 GCloud 在 Beta 中运行许多服务,并没有真正为生产做好准备;我会远离 GCF,或者可能会在 6 个月后重新访问。
编辑:请参阅 https://issuetracker.google.com/issues/66695033 GCloud 团队声称已修复但我还没有时间测试;我的package方式只需要一个云虚拟机,而且非常便宜。