簡體   English   中英

如何通過任務名稱對Celery任務進行評分?

[英]How to rate limit Celery tasks by task name?

我正在使用Celery處理來自Django應用程序的異步任務。 大多數任務都很簡短,幾秒鍾即可完成,但是我有一項任務可能要花幾個小時。

由於服務器上的處理限制,Celery配置為一次只能運行2個任務。 這意味着,如果有人啟動了這些長期運行的任務中的兩個,則會有效地阻止整個其他Celery處理站點數小時,這非常糟糕。

有什么方法可以配置Celery,使其一次只能處理一種類型的任務? 就像是:

@task(max_running_instances=1)
def my_really_long_task():
    for i in range(1000000000):
        time.sleep(6000)

注意,我不想取消所有其他的my_really_long_task啟動。 我只是不希望他們立即開始,只等所有同名的其他任務完成后再開始。

由於Celery似乎不支持此功能,因此我當前的hacky解決方案是查詢任務中的其他任務,如果找到其他正在運行的實例,則將自己重新安排為稍后運行,例如

from celery.task.control import inspect

def get_all_active_celery_task_names(ignore_id=None):
    """
    Returns Celery task names for all running tasks.
    """
    i = inspect()
    task_names = defaultdict(int) # {name: count}
    if i:
        active = i.active()
        if active is not None:
            for worker_name, tasks in i.active().iteritems():
                for task in tasks:
                    if ignore_id and task['id'] == ignore_id:
                        continue
                    task_names[task['name']] += 1
    return task_names

@task
def my_really_long_task():

    all_names = get_all_active_celery_task_names()
    if 'my_really_long_task' in all_names:
        my_really_long_task.retry(max_retries=100, countdown=random.randint(10, 300))
        return

    for i in range(1000000000):
        time.sleep(6000)

有一個更好的方法嗎?

我知道像其他哈克解決方案的這個 ,而是建立一個獨立的內存緩存服務器來跟蹤任務的獨特性就更加不可靠,而且比我上面使用的方法更加復雜。

另一種解決方案是將my_really_long_task排隊到單獨的隊列中。

 my_really_long_task.apply_async(*args, queue='foo')

然后啟動並發性為1的工作器來使用這些任務,以便一次僅執行1個任務。

celery -A foo worker -l info -Q foo

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM