Google app engine 使db.put()成为故障保护

Google app engine 使db.put()成为故障保护,google-app-engine,google-cloud-datastore,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.d

我希望在我的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的请求截止日期过期。即使此类事件的频率较低,但如果流量较大,其数量可能相当大。这些都是我试图涵盖的情况。

我不会说这是最好的方法-无论是什么原因导致了最初的异常,都很可能再次发生。我要做的是,首先将要保存的记录加载到memcache中,如果发生put异常(任何异常),它可以尝试一定次数的重试(例如3次),每次尝试之间有一个短暂的睡眠。根据应用程序的不同,这可能是一个同步操作,也可能是使用延迟任务,可以使用memcache中的数据异步完成。

最后,我实际上会对数据存储中的记录进行查询,即使没有异常来确认行是否已实际写入

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

  • 在put操作过程中可能会引发更多的异常(如InternalError、Timeout、CommitteedButStillApplying、TransactionFailedError) 其中一些并不意味着看跌期权失败。(即CommitteedButStillApplying仅表示put操作延迟)。使用这种方法,在延迟调用成功后,数据存储中将有两次该条目
  • 任务限制为~100KB(总大小,而非有效负载)。如果您的负载接近或高于该限制,延迟api将自动尝试 将有效负载序列化到数据存储,以使任务本身低于该限制。如果数据存储真的不可用,这也会失败

因此,最好捕获数据存储错误,并通知您的用户他的请求失败。

重试很好,但是使用指数退避和最重要的正确事务使用,这样失败X不会以部分写入结束。

我不同意。这意味着要防止的异常是非确定性的,如基础设施问题、高数据存储延迟、过载等,而不是确定性的,如编码错误。taskqueue通过优雅地减少重试间隔来管理再次发生的概率。另一方面,感谢您提供的避免双重提交的提示。在我的情况下,重复的流式数据并不重要,但这肯定是一个需要考虑的问题。啊,我同意你关于捕获特定异常的观点,我绝对同意在发生故障的情况下仍然应该实施适当的异常管理,但使用断路器重试功能(无论是通过任务队列还是同步)是管理临时非确定性问题的常用技术。如果在向数据存储写入一行时出现问题,请回答以下问题,我不会假设“数据存储已关闭”,我将首先通过合理的重试次数来确认这一点。完成后,向用户显示错误消息。感谢这些提示。实际上,我并不过分担心“数据存储崩溃”的情况,而是间歇性错误,正如问题中所阐明的那样。