【发布时间】:2018-09-23 13:25:22
【问题描述】:
更新:我已经稍微缩小了问题的范围,所以我删除了不必要的代码和示例:
更新 2:在让 cron 作业以 12 小时间隔运行一段时间后(每次都成功结束,但没有用 BQ 写任何内容),我们震惊地发现,大约一周后,其中一个 cron作业确实成功写入 BigQuery,以及 Stackdriver 日志指出“此请求导致为您的应用程序启动一个新进程 (...)”,如下所示。以下作业再次停止写入。现在我想知道这是否以某种方式连接到缓存的应用程序状态(有一些过期时间)或凭据过期日期,这会以某种方式阻止在第一次之后进一步写入 BigQuery,但不会导致错误。
问题描述:
我正在尝试在 App Engine(标准)中设置一个 cron 作业,以从 BigQuery 查询数据并将数据写回 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.
我试过了:
为默认 appengine 服务帐号添加 BigQuery DataOwner 和 User 权限,但没有效果。
有人提到标准应用引擎不完全支持 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'
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)
cron.yaml:
cron:
- url: /bigquerycron
schedule: every 30 minutes
【问题讨论】:
-
您是在计算引擎上运行它,还是每次要执行操作时都登录到云外壳?
-
这是作为使用 App Engine 部署的应用程序运行的,为了进行测试,我通过云 shell 运行这些脚本(手动执行 .py 文件)并且我没有任何问题,但问题是它何时被安排使用自动 cron 作业。
-
您是否尝试过在实例上使用 Crontab 而不是 Cron 作业进行调度,只是为了消除这个潜在问题?此外,您可以将 .json 客户端凭据显式添加到您的 Python 代码中以使用服务帐户吗?
-
我想使用 cron 作业,因为这只是我们想用它实现的第一个用例。至于我以前从未使用过的凭据(实际上是任何形式的身份验证),您能否通过示例修改我帖子中的第一个 bigquerycron.py 以便我对其进行测试?
-
我在我的自动化 Python 脚本中使用
client = bigquery.Client.from_service_account_json("my_file.json"),该文件位于实例的本地目录中。尝试在您的代码中使用它并添加到您的 .json 凭据文件中。
标签: python-2.7 google-app-engine cron google-bigquery