【问题标题】:What's the best way of scheduling a task that runs over ten minutes in Google App Engine?在 Google App Engine 中安排运行十分钟以上的任务的最佳方式是什么?
【发布时间】:2015-08-05 10:49:24
【问题描述】:

假设我有一个运行一个小时的脚本。它所做的只是睡一个小时,并在该小时结束时更改数据存储区中的某些内容。

def task(keyname):
    time.sleep(3600)
    q = Item.all()
    item = q.filter("keyname = ", "%s" % keyname).get()
    item.value += 1
    item.put()

实现这一目标的最佳方法是什么?

cron 文档说“由 cron 调用的 HTTP 请求最多可以运行 10 分钟,但受到与其他 HTTP 请求相同的限制。”我假设这意味着运行超过十分钟的 cron 任务将会中断。

我查看了任务队列文档,但我不想将这些任务一个接一个地排队。我希望它们同时发生。

我正在考虑添加一个计数器属性并每分钟运行一次任务而不是休眠:

def task(keyname):
    q = Item.all()
    item = q.filter("keyname = ", "%s" % keyname).get()
    if item.counter == 60:
        item.value += 1
        item.put()
    else:
        item.counter += 1
        item.put()

但是访问数据库的次数太多了。

那么,有人有更聪明的解决方法吗?

【问题讨论】:

    标签: python google-app-engine cron


    【解决方案1】:

    cron 作业命中一个处理程序,该处理程序启动一个任务。这个过程通常需要不到一秒钟的时间。之后,只要您需要,该任务就可以运行——如果有必要,可以永远运行。这一切都取决于on the target of a task。 10 分钟限制仅适用于前端(F 型)实例。

    如果需要,您可以同时运行多个任务。

    【讨论】:

    • 谢谢。在手动缩放实例上运行的后台线程似乎是我需要的。
    【解决方案2】:

    当您说您希望“这些任务”同时发生时,我不明白您的意思;你只提到了一个任务。

    无论如何,任务队列就是这样做的方式。您可以使用 Task 构造函数的 countdown 参数来告诉它在 3600 秒内执行。

    我通常更喜欢使用deferred library,它可以动态创建任务而无需设置特定的处理程序:

    from google.appengine.ext import deferred
    ...
    deferred.defer(my_task, _countdown=3600)
    

    【讨论】:

    • 我在想如果我在第 0 分钟安排任务 #1,在第 10 分钟安排任务 #2,任务 #1 将在第 60 分钟完成,任务 #2 将在第 120 分钟完成(因为它在任务 #1 之后开始,因为它是一个队列)。我希望第 1 项任务在第 60 分钟完成,第 2 项任务在第 70 分钟完成。很抱歉造成混乱。
    【解决方案3】:

    @Soricidae,你正在构建一个 cron 任务。

    1. 为此,您需要有一个处理程序来调用您的方法task
    2. 此外,您需要指定到该处理程序的 URL 路由。
    3. 然后您需要在 cron.yaml 中指定一个调用 task 方法的 cronjob。

    *。此外,我强烈建议使用任务队列,以便 appengine 解决您在 cron 任务期间的加载时间问题。

    例如,在我的例子中,我有一个欢迎处理程序,它向用户发送电子邮件,每 24 小时检查一次超过 1 天尚未受到欢迎的新用户...

    所以,我定义了以下路由(1 个用于 cronjob,1 个用于任务队列):

    RedirectRoute('/cronjob-welcome/', handlers.WelcomeCronjobHandler, name='cronjob-welcome', strict_slash=True),
    RedirectRoute('/taskqueue-welcome/', handlers.WelcomeHandler, name='taskqueue-welcome', strict_slash=True),
    

    然后,我定义了一个 cronjob 处理程序,一旦调用它就可以将真正的操作处理程序用作任务队列,请参阅:

    class WelcomeCronjobHandler(BaseHandler):
        def get(self):
            welcome_url = self.uri_for('taskqueue-welcome')
            taskqueue.add(url=welcome_url, params={
                'offset': 0
            })
    

    你可以看到这个handler请求welcome_url,它在路由中调用定义好的handlertaskqueue-welcome并做了以下事情:

    class WelcomeHandler(BaseHandler):
        """
        Core Handler for sending users welcome message
        Use with TaskQueue
        """
    
        @taskqueue_method
        def post(self):
            # ... MY CODE FOR EMAILING USERS ....
            # ... YOUR CODE SHOULD GO IN HERE ...
    

    最后,为了每 24 小时调用一次 cronjob 处理程序,我在 cron.yaml 文件中添加了以下内容,请注意 cronjob-welcome 的路由:

    - description: welcome messaging
      url: /cronjob-welcome/
      schedule: every day 13:00
    

    总结一下,我的 cron.yaml 每天 13:00 调用 cronjob 处理程序,同时触发 taskqueue 处理程序,它调度一个 google appengine 任务队列来解决我的计划任务

    希望这会有所帮助。

    【讨论】:

    • 感谢您详细解释 cron 任务如何与任务队列交互。但是,我不认为任务队列是我需要的,因为我假设它是一个队列,并且它是一个队列,一旦第一个任务完成,它将在第二个任务上开始。我想要的是可以同时运行多个任务的东西。
    • 例如,假设我运行了两个都需要 60 分钟才能运行的任务。我在第 0 分钟开始第一个任务,在第 10 分钟开始第二个任务。我想要的是第一个任务在第 60 分钟完成,第二个任务在第 70 分钟完成。我想我需要的只是击中具有 cron 请求而不是任务队列的基本/手动扩展实例。谢谢你教我 cronjob 处理程序是如何工作的。我只是在查找它的过程中。
    猜你喜欢
    • 1970-01-01
    • 2022-10-30
    • 2010-10-06
    • 1970-01-01
    • 2014-01-12
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多