我正在使用App Engine标准环境(自动标量),这意味着在取消请求之前我有10分钟的限制。
目标是定期查询BigQuery中的数据,并为每条记录在任务队列中创建一个任务,以便可以在后台处理记录。
https://cloud.google.com/bigquery/create-simple-app-api州的指示等待这样的工作:
// Create a job ID so that we can safely retry.
JobId jobId = JobId.of(UUID.randomUUID().toString());
Job queryJob = bigquery.create(JobInfo.newBuilder(queryConfig).setJobId(jobId).build());
// Wait for the query to complete.
queryJob = queryJob.waitFor();
问题是10分钟的限制,因为BigQuery查询是在后台处理的,并且可能需要一些时间才能得到结果,所以我可能无法在同一个端点调用中处理响应。
我知道我可以配置App Engine来延长每个请求的最长时间,但这几乎不是解决方案。
答案 0 :(得分:0)
一种可靠的方法是处理应用程序代码中的作业生命周期管理,而不是依赖于自动为您执行此操作的包装器(在作业完成之前阻塞的包装器)。
来自Running jobs:
以编程方式运行作业:
使用唯一的job ID generated by your client code调用
jobs.insert
方法来开始工作。服务器生成一个作业 如果省略它,则为您提供ID,但最佳做法是生成 客户端的作业ID允许可靠地重试jobs.insert
调用调用
jobs.insert
方法时,请包含作业资源 包含指定作业类型的子属性的表示 - load,query,extract或copy。通过使用作业ID调用
jobs.get
检查作业状态,并检查status.state
值以了解作业状态。什么时候status.state
为DONE
,作业已停止运行;但是,aDONE
状态并不意味着作业仅成功完成 它不再运行了。注意:有一些管理作业状态的包装函数 请求你。例如,运行
jobs.query
会创建一个作业 定期轮询DONE
状态指定的时间段。- 醇>
检查工作是否成功。如果作业具有
status.errorResult
属性,则作业失败。status.errorResult
属性成立 描述失败工作中出错的信息。如果status.errorResult
缺席,工作成功完成, 虽然可能存在一些非致命错误,例如问题 在加载作业中导入几行。返回非致命错误 工作的status.errors
列表。
基本上不是使用单个阻塞调用来等待作业完成(在您的情况下为queryJob.waitFor();
,相当于引用中提到的jobs.query
),您可以启动后台作业,然后进行重复调用查询作业的状态(例如在延迟推送队列任务中),当它完成时,您实际上开始处理结果。
可能感兴趣的还有Introduction to BigQuery Jobs和Managing BigQuery Jobs。
注意:答案完全基于文档,我还不是BigQuery用户。
答案 1 :(得分:0)
最好的选择是处理长时间运行的任务,如BQ所做的那样:提供一个job-id并允许客户端查询它,在查询尚未完成时返回202,并在结果为200时返回结果结果已准备好供客户使用。
此外,202可以返回正文,因此您可以为客户端设置不同的状态(例如“排队”,“正在运行”,“处理结果”,......)。
在服务器端,您启动一个查询,并在BQ返回作业ID后立即将其存储在某个持久存储中(我会选择Datastore,但它可能是memcache, cloudSQL实例,甚至是GCS中的文件。)
然后,您只需创建一个cron job来检查BQ以查找未完成查询的状态,并相应地更新其在持久存储中的状态。 BQ作业完成后,您可以检索结果并存储它们,以便在客户端检查您的服务时准备好它们。
例如,这是您应该在应用中执行的BQ API查询(在此处使用curl提供示例,您可以稍后使用idiomatic libraries翻译为任何语言):
创建作业,从响应中检索作业ID,然后存储它:
PROJECT=$(gcloud config get-value project)
QUERY='SELECT * FROM `bigquery-samples.wikipedia_benchmark.Wiki1k` limit 0'
curl -H"Authorization: Bearer $(gcloud auth print-access-token)" -H'content-type:application/json' https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs -d"
{
\"configuration\": {
\"query\": {
\"query\": \"$QUERY\",
\"useLegacySql\": false
}
},
\"jobReference\": {
\"projectId\": \"$PROJECT\"
}
}"|jq -r .jobReference.jobId >> running_jobs
继续查询BQ API以了解作业状态。 (这可能是你的cron工作):
for job in $(cat running_jobs); do
if [ $(curl -H"Authorization: Bearer $(gcloud auth print-access-token)" https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs/$job|jq -r .status.state) = "DONE" ]; then
# here your processing part including your callback
# then remove the job from the list of running jobs
sed -i "/$job/d" ./running_jobs
fi
done
您可以在cloud shell中尝试此操作。