谷歌应用引擎是否可以增加响应超时时间?

6
在我的本地机器上,这个脚本可以很好地运行,但在云端却总是500。这是一个定时任务,所以如果需要5分钟,我并不介意...
< class 'google.appengine.runtime.DeadlineExceededError' >:
有什么想法是否可以增加超时时间?
谢谢,rui
3个回答

10

您不能超过30秒的时间限制,但是您可以通过使用任务队列间接增加超时时间-编写任务来逐步迭代数据集并处理它。每次运行此类任务时,当然应该符合超时限制。

编辑

更具体地说,您可以使用数据存储查询游标在相同位置恢复处理:

http://code.google.com/intl/pl/appengine/docs/python/datastore/queriesandindexes.html#Query_Cursors

首次引入于SDK 1.3.1:

http://googleappengine.blogspot.com/2010/02/app-engine-sdk-131-including-major.html


9

关于数据库查询超时的规则非常复杂,但似乎一次查询不能超过约2分钟,而批处理不能超过约30秒。以下是一些使用游标将作业分成多个查询以避免超时的代码。

def make_query(start_cursor):
  query = Foo()

  if start_cursor:
    query.with_cursor(start_cursor)

  return query

batch_size = 1000
start_cursor = None

while True:
  query = make_query(start_cursor)
  results_fetched = 0

  for resource in query.run(limit = batch_size):
    results_fetched += 1

    # Do something

    if results_fetched == batch_size:
      start_cursor = query.cursor()
      break
  else:
    break

1
说“查询不能超过30秒”并不完全准确-请参见此处的讨论,特别是评论#8及其后续内容:https://code.google.com/p/googleappengine/issues/detail?id=12243 - tom
@tom:所以,一个批处理可以运行30秒,但一个查询可能需要大约4分钟?如果是这样,你建议我如何编辑我的答案? - phatmann
@tom,你能解释一下为什么我需要在查询中添加.run(limit = batch_size)吗? - phatmann
好问题!@Patrick Costello在他的建议代码中包含了它,所以我假设它是正确的,但你检查是对的!至于为什么:我的假设是将查询限制在“我们的批次”大小内,可以防止AE预取超出我们限制的结果/批次。我理解GAE在处理当前批次时自动获取下一批次,但我不知道所有细节。我们的break无法被GAE预测,因此我认为GAE不能优化其DB RPC而没有limit提供的提示。也许有人不是猜测可以发表意见? - tom
太好了!现在我们需要将这个答案设为“被采纳”的答案。它肯定比其他答案更有用。 - tom
显示剩余2条评论

1
以下是我用来解决这个问题的代码,通过将一个大查询分解成多个小查询。我使用了google.appengine.ext.ndb库--我不知道是否需要该代码才能工作。
(如果您没有使用ndb,请考虑切换到它。它是db库的改进版本,并且迁移到它很容易。有关更多信息,请参见https://developers.google.com/appengine/docs/python/ndb。)
from google.appengine.datastore.datastore_query import Cursor

def ProcessAll():
  curs = Cursor()
  while True:
    records, curs, more = MyEntity.query().fetch_page(5000, start_cursor=curs)
    for record in records:
      # Run your custom business logic on record.
      RunMyBusinessLogic(record)
    if more and curs:
      # There are more records; do nothing here so we enter the 
      # loop again above and run the query one more time.
      pass
    else:
      # No more records to fetch; break out of the loop and finish.
      break

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接