使db.put()失效保护

时间:2013-03-27 02:41:34

标签: google-app-engine google-cloud-datastore

我希望我的Google App Engine服务中的db.put()操作尽可能具有弹性,即使在基础设施出现问题或过载的情况下也要尽量提高成功的可能性。我现在想出的是捕获可能发生的每个可能的异常,并创建一个在第一次尝试失败时重试提交的任务:

try:
    db.put(new_user_record)
except DeadlineExceededError:
    deferred.defer(db.put,new_user_record)
except:
    deferred.defer(db.put,new_user_record)

此代码是否会捕获所有可能的错误路径?或者有没有其他方法db.put()可以失败,这不会被此代码捕获?


2013年3月28日编辑 - 澄清何时出现故障

到目前为止,答案似乎假设如果db.put()失败则是因为数据存储区已关闭。根据我运行相当高工作负载的应用程序的经验,这不一定是必需的。有时您遇到特定于工作负载的API瓶颈,有时一个API的缓慢导致请求截止日期在另一个API中到期。尽管此类事件频率较低,但如果流量较高,则其数量可能相当大。这些是我想要涵盖的情况。

3 个答案:

答案 0 :(得分:1)

我不会说这是最好的方法 - 无论是什么导致原始异常都可能再次发生。我要为额外的弹性做些什么是首先加载要保存到memcache中的记录,并且在put(任何异常)发生异常的情况下,它可以尝试进行一定数量的重试(例如3),每次重试之间有一个短暂的睡眠。尝试。根据您的应用程序,这可以是同步操作,也可以是使用延迟任务,可以使用memcache中的数据异步完成。
最后,我实际上对数据存储中的记录进行查询,即使没有异常来确认该行实际已被写入。

答案 1 :(得分:1)

嗯,我认为尝试这样的后备不是一个好主意。如果数据存储区已关闭,它会关闭并且你运气不好(不应经常发生:) 对您的代码的一些想法:

  • 在put-opertation期间可能会引发更多异常(例如InternalError,Timeout,CommittedButStillApplying,TransactionFailedError) 其中一些并不意味着放置失败。 (即CommittedButStillApplying只是意味着put操作延迟)。使用您的方法,在延迟呼叫成功后,您最终会在数据存储区中输入两次该条目。
  • 任务限制在~100KB(总大小,不是有效负载)。如果您的有效负载接近或超过该限制,则deferred-api将自动尝试 将有效负载序列化到数据存储区,以使任务本身保持在该限制之下。如果数据存储确实不可用,那么也会失败。

因此,捕捉数据存储错误可能会更好,并告知用户他的请求失败。

答案 2 :(得分:0)

重试是好的,但是使用指数退避和最重要的正确事务使用,以便失败xoesnt结束部分写入。