在 Google App Engine 上处理 db.Timeout

Posted

技术标签:

【中文标题】在 Google App Engine 上处理 db.Timeout【英文标题】:Dealing with db.Timeout on Google App Engine 【发布时间】:2009-09-21 18:33:05 【问题描述】:

我正在测试我的应用程序(在 Google App Engine 实时服务器上)以及我编写它的方式,我的代码中有大约 40 个 db.GqlQuery() 语句(大部分是类的一部分)。

我不断收到 db.Timeout 非常频繁

我该如何处理?我打算用这样的非常残酷的代码来包围我的所有查询:

查询成功 = 假 而不是 querySucceeded : 尝试 : 结果 = db.GqlQuery("""xxx""").get() querySucceeded = True #只有在上面的行没有引发 exc 时才到这里 除了 : 查询成功 = 假

这样好吗?你同意?有什么更好的方法来处理 db.Timeouts?

编辑:

我现在将它用于任何获取查询

""" 查询得到单个结果 """ 定义查询获取(gql): 查询成功 = 假 而不是 querySucceeded : 尝试 : 结果 = db.GqlQuery(gql).get() querySucceeded = True #只有在上面的行没有出现时才到这里 除了 : 查询成功 = 假 返回结果

我有类似的 fetch 和 count 函数。

【问题讨论】:

gaeutilities.appspot.com/rotmodel 我在上面展示的解决方案正在工作,但我不知道我是否应该预见到任何重大问题,或者是否有更好的方法来做到这一点。 Appengine 根本没有挂起,只是有时查询会失败.. 我想添加一个评论,指出频繁失败并需要重试这些查询adds to your cost。 GAE 已经(并且确实)有一些严重的性能问题。 【参考方案1】:

这是一个重试 db.Timeout 的装饰器,改编自 Kay 框架:

import logging, time
from google.appengine.ext import db

def retry_on_timeout(retries=3, interval=1.0, exponent=2.0):
    """A decorator to retry a given function performing db operations."""
    def _decorator(func):
        def _wrapper(*args, **kwargs):
            count = 0
            while True:
                try:
                    return func(*args, **kwargs)
                except db.Timeout, e:
                    logging.debug(e)
                    if count >= retries:
                        raise e
                    else:
                        sleep_time = (exponent ** count) * interval
                        logging.warning("Retrying function %r in %d secs" %
                            (func, sleep_time))
                        time.sleep(sleep_time)
                        count += 1

        return _wrapper

    return _decorator

要使用它,只需装饰任何执行 db 操作并且您想要重试的函数:

@retry_on_timeout()
def do_the_stuff(models):
    return db.put(models)

【讨论】:

【参考方案2】:

查询偶尔会失败。您可以像上面那样向用户显示错误消息,或者重试。但是,如果您重试,您应该使用 thread.sleep 在每次重试时增加延迟量(例如,从 50 毫秒开始) - 如果重试不尽快重试,则重试更有可能成功。

每个请求 40 个查询是 很多。您应该考虑重构您的代码 - 必须可以消除其中的大部分!

【讨论】:

【参考方案3】:

看看这个 python 自动重试数据存储超时配方。类似于 moraes answer,但您只需要在初始化时调用一次,而不是装饰执行数据存储操作的函数。

http://appengine-cookbook.appspot.com/recipe/autoretry-datastore-timeouts

【讨论】:

【参考方案4】:

在 GAE-Utilities 中查看新的 ROTModel。下面的第二个讨论显示了它如何重试。 它是 db.Model 的子类,因此您的类可以从 ROTModel 继承,并利用它的重试。

http://code.google.com/p/gaeutilities

http://groups.google.com/group/google-appengine/browse_thread/thread/ac51cc32196d62f8/aa6ccd47f217cb9a?lnk=gst&q=timeout#aa6ccd47f217cb9a

【讨论】:

以上是关于在 Google App Engine 上处理 db.Timeout的主要内容,如果未能解决你的问题,请参考以下文章

在 Google 虚拟机上处理来自 Google App Engine 的数据

使用 Google App Engine 在 HTML 和 CSS 上呈现模板

Google App Engine“解析./app.yaml时出错:未知的url处理程序类型”

Google-App-Engine 上的 Grails - 它死了吗? [关闭]

带有Firebase的Google App Engine-无法添加依赖项

从 Google App Engine 发送请求