2016-04-14 38 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等)。