Vae*_*qal 5 cron google-app-engine python-2.7 google-bigquery
更新:我已经缩小了一点问题,所以我删除了不必要的代码和示例:
更新2:离开cron作业以12小时的间隔运行一段时间后(每次结束都成功,但没有在BQ中写入任何内容)我们震惊地发现,大约一周后,其中一个cron作业成功完成写入BigQuery,以及Stackdriver日志,声明"此请求导致为您的应用程序启动一个新进程(...)",如下所示.以下工作再次停止写作.现在我想知道这是否以某种方式连接到缓存的应用程序状态(有一些过期时间)或凭据到期日期,以某种方式阻止在第一次之后进一步写入BigQuery,但不会导致错误.
问题描述:
我正在尝试在App Engine中设置一个cron作业(标准)来查询并将数据写回BigQuery(数据集与部署的应用程序在同一个项目中)并且cron作业成功执行但只写入BigQuery部署后首次执行,之后它们仍然成功执行但不写入.
我发现的主要区别在于Stackdriver日志,对于正确写入的执行,有额外的调试和信息,对于后续的没有这样的消息:
2018-04-19 04:44:03.933 CEST
Converted retries value: 3 -> Retry(total=3, connect=None, read=None, redirect=None, status=None) (/base/data/home/apps/e~<redacted>/lib/urllib3/util/retry.py:200)
2018-04-19 04:44:04.154 CEST
Making request: POST https://accounts.google.com/o/oauth2/token (/base/data/home/apps/e~<redacted>/lib/google/auth/transport/requests.py:117)
2018-04-19 04:44:04.160 CEST
Starting new HTTPS connection (1): accounts.google.com (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:824)
2018-04-19 04:44:04.329 CEST
https://accounts.google.com:443 "POST /o/oauth2/token HTTP/1.1" 200 None (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:396)
2018-04-19 04:44:04.339 CEST
Starting new HTTPS connection (1): www.googleapis.com (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:824)
2018-04-19 04:44:04.802 CEST
https://www.googleapis.com:443 "POST /bigquery/v2/projects/<redacted>/jobs HTTP/1.1" 200 None (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:396)
2018-04-19 04:44:04.813 CEST
This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
Run Code Online (Sandbox Code Playgroud)
我试过了:
为默认的appengine服务帐户添加BigQuery DataOwner和用户权限,但没有任何效果.
有人提到标准应用引擎并不完全支持google.cloud库,所以我尝试使用OAuth2/httplib2/googleapiclient凭据进行身份验证,但这是我第一次尝试它并且我不明白如何放置碎片,没有google.cloud库我不知道如何为BQ写一个正确的查询
其他凭据设置方法如下所示,但似乎连接到BQ不是问题,它们都连接和写入(一次),只是在已部署的应用引擎中重复它.
以下是完整的实施:
app.yaml中:
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /bigquerycron
script: bigquerycron.app
login: admin
libraries:
- name: ssl
version: latest
env_variables:
GAE_USE_SOCKETS_HTTPLIB : 'true'
Run Code Online (Sandbox Code Playgroud)
bigquerycron.py
from __future__ import absolute_import
from google.cloud import bigquery
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('CRON test page')
def writeDataTest(dataset_id = '<redacted>',table_id='<redacted>'):
client = bigquery.Client.from_service_account_json("credentials.json")
job_config = bigquery.QueryJobConfig()
table_ref = client.dataset(dataset_id).table(table_id)
job_config.destination = table_ref
job_config.write_disposition = 'WRITE_APPEND'
query_job = client.query(
"""SELECT CURRENT_DATETIME() AS Datetime, 'CRON' as Source""", job_config=job_config)
writeDataTest()
app = webapp2.WSGIApplication([
('/bigquerycron', MainPage),
], debug=True)
Run Code Online (Sandbox Code Playgroud)
cron.yaml:
cron:
- url: /bigquerycron
schedule: every 30 minutes
Run Code Online (Sandbox Code Playgroud)
在这种特定情况下,凭证不是问题,问题只是由于对 App Engine 工作方式的误解而导致函数调用的放置。bigquery 的函数调用应移至 MainPage 类定义内,固定的 bigquerycron.py 如下所示(仅移动一行代码):
from __future__ import absolute_import
from google.cloud import bigquery
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('CRON test page')
writeDataTest()
def writeDataTest(dataset_id = '<redacted>',table_id='<redacted>'):
client = bigquery.Client.from_service_account_json("credentials.json")
job_config = bigquery.QueryJobConfig()
table_ref = client.dataset(dataset_id).table(table_id)
job_config.destination = table_ref
job_config.write_disposition = 'WRITE_APPEND'
query_job = client.query(
"""SELECT CURRENT_DATETIME() AS Datetime, 'CRON' as Source""", job_config=job_config)
app = webapp2.WSGIApplication([
('/bigquerycron', MainPage),
], debug=True)
Run Code Online (Sandbox Code Playgroud)
OP 中的版本确实只向 BigQuery 写入一次,当 App Engine 应用程序首次加载时,所有后续调用都只执行 MainPage 类,在这种情况下,该类什么也不做,因为实际的 BigQuery 代码位于其外部。
此外,在不使用 google-cloud-python 库的情况下重写应用程序将是有益的,GAE 标准不支持该库(https://github.com/GoogleCloudPlatform/google-cloud-python/issues/1893)。这是特别不幸的,因为即使是 python 的官方 bigquery 文档(https://cloud.google.com/bigquery/docs/)也使用了这个库。不过,有多种解决方法可以继续使用它,包括链接的 github 问题和此处提到的一些解决方法: 在 GAE 中使用 gcloud-python,本示例中使用了类似的解决方法。
但如前所述,最好使用专门的 Python API 客户端库: https ://developers.google.com/api-client-library/python/
| 归档时间: |
|
| 查看次数: |
583 次 |
| 最近记录: |