2016-04-14 71 views
4

我对Heroku的分布式环境中将要触发一次的事件安排必要的软件设计有疑问。如何在Heroku中的Django中安排一次性事件?

我相信最好写出自己想要达到的目标,但是我确实已经完成了自己的研究,即使经过两个小时的工作,我也无法自己弄清楚。

让我views.py说我有一个功能:

def after_6_hours(): 
    print('6 hours passed.') 


def create_game(): 
    print('Game created') 
    # of course time will be error, but that's just an example 
    scheduler.do(after_6_hours, time=now + 6) 

,所以我想达到的目标是能够运行after_6_hours功能create_game已被调用刚好是6个小时后。现在,正如您所看到的,此功能是在通常的clock.pytask.py等文件中定义的。

现在,我该如何让我的整个应用程序始终在Heroku中运行,并且能够将此作业添加到这个虚构的scheduler库的队列中?

在旁注中,我无法使用Heroku的Temporizer插件。 APScheduler和Python rq的结合看起来很有希望,但是示例很简单,都安排在clock.py的同一个文件中,我只是不知道如何将所有内容与我的设置绑定在一起。提前致谢!

+1

因此,IIUC你有一个网络应用程序分布在多个节点,并希望运行一个任务(它调用一个函数)6个小时后,只有一个节点...为什么不是[芹菜](http: //celery.readthedocs.org/en/latest/userguide/calling.html)你需要什么? –

+0

@PeterBrittain Heroku将节点及其环境抽象出来。它被称为测功机。我关心的不是节点。我担心的是能够在这种环境下建立一个功能齐全的作业调度系统,而且我无法想出办法。我想到的是我需要有3个dynos。一个用于服务我的应用程序,一个用于调度程序(它将解析预定作业),另一个用于执行这些任务。在我的“views.py”中,我希望能够添加到预定作业的数据库中,以便日后调度程序dyno可以解析它。现在,我想准备好这个设置。 –

+0

我可以通过正确的文档获得Celery的启动和运行,或基本上任何其他工作调度。细节并不重要。我正在寻找拥有这个调度工作/任务系统的更大图景。 –

回答

3

在Heroku中,您可以让您的Django应用程序在Web Dyno中运行,该应用程序将负责为您的应用程序提供服务并安排任务。 例如(请注意,我没有测试运行代码):

创建after_hours.py,它将具有您要安排的功能(请注意,我们将在工作人员中使用相同的源代码)。

from redis import Redis 
from rq_scheduler import Scheduler 
from datetime import timedelta 

from after_hours import after_6_hours 

def create_game(): 
    print('Game created') 

    scheduler = Scheduler(connection=Redis()) # Get a scheduler for the "default" queue 
    scheduler.enqueue_in(timedelta(hours=6), after_6_hours) #schedules the job to run 6 hours later. 

调用create_game()应该安排after_6_hours()来运行:

def after_6_hours(): 
     print('6 hours passed.') 
views.py使用 rq(注意,单独 rq是不够的,在您的情况为您安排的任务),并 rq-scheduler

6小时后。
提示:您可以使用Redis To Go附加组件在Heroku中配置Redis

下一步是运行rqscheduler工具,该工具每分钟轮询Redis以查看当时是否有任何工作要执行并将其放入队列中(工作人员将要侦听到该工作)。现在

,在Worker Dyno创建一个文件after_hours.py

def after_6_hours(): 
    print('6 hours passed.') 
    #Better return something 

并创建另一个文件worker.py

import os 

import redis 
from rq import Worker, Queue, Connection 

from after_hours import after_6_hours 

listen = ['high', 'default', 'low'] # while scheduling the task in views.py we sent it to default 

redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379') 

conn = redis.from_url(redis_url) 

if __name__ == '__main__': 
    with Connection(conn): 
     worker = Worker(map(Queue, listen)) 
     worker.work() 

并运行此worker.py

python worker.py 

这应该运行计划任务(afer_6_hours在这种情况下)在工人Dyno。 请注意,这里的关键是为工作人员提供相同的源代码(在这种情况下为after_hours.py)。同样是在rq强调docs

确保工人和工作产生份额完全 相同的源代码。

如果有帮助,docs中有一个暗示来处理不同的代码库。

对于情况下幅进程不具有访问源代码 在工人运行(即代码库X调用从代码基部Y延迟功能 ),可以传递函数作为字符串参考, 也。

q = Queue('low', connection=redis_conn) 
q.enqueue('my_package.my_module.my_func', 3, 4) 

希望rq-scheduler太尊重传递字符串而不是函数对象的这种方式。

只要你理解这个东西,你就可以使用任何模块/调度工具(Celery/RabbitMQ,APScheduler等)。