GAE上是否始终保证排队任务的执行?

时间:2012-09-08 13:01:31

标签: google-app-engine task-queue

以下简单模式是否足以确保即使在应用程序更新或严重“不稳定”的谷歌失败后,任务序列也不会停止。

def do_work():
    ... .... 

    deferred.defer(do_work, _countdown=..in 7 days..)

我可以安排这样一个自我调度的工作人员,永远不要回头吗?

2 个答案:

答案 0 :(得分:2)

两个答案:

是的,任务最终会执行,并且还会在任务执行出错时重试执行。定义任务时会设置重试选项。

不,任务队列不是调度程序,因此您无法安排任务在特定时间运行。放入任务队列的任务将以FIFO方式立即提供。

正如@Jesse所指出的,对于安排工作,你应该研究GAE cron。

答案 1 :(得分:1)

如果任务排队成功,它最终会执行。 (并且App Engine会一直尝试。)

您使用cron jobs可能会更好地实现您显示的模式,它会定期运行任务。我使用的一个常见模式是让每日cron作业启动任务队列上的任务并进行少量重试(这样如果出现临时故障,它将立即重试)。

如果你确实想使用上面的方法,而不是cron,还有另一件事需要担心:因为你的方法可能因为失败或其他系统问题(例如运行它的实例发生故障)而重试,你应该做确定你最终没有完成两项任务。想象一下,如果它运行,注册下一个任务然后节点发生故障; App Engine将重试,开始第二项任务。为了防止这种情况,您可以使用数据存储(在事务中)来测试并查看下一个任务是否已经入队。类似的东西:

def do_work(counter):
    ...

    @db.transactional
    def start_next():
        # fetch myModel from the data store here
        if myModel.counter == counter:
            return # already started next job
        myModel.counter = counter
        myModel.put()
        deferred.defer(do_work, counter + 1, _transactional=True, _countdown=...)

    start_next()

注意延迟通话中的“交易”参数;这可确保当且仅当下一个任务入队时才更新MyModel实例。

您可能还希望在一定次数的失败重试后向管理员发送电子邮件。 (您可以在请求HTTP标头中找到它,但如果您想这样做,则不能使用延迟库;您必须直接使用任务队列API。)