簡體   English   中英

使用主題交換運行多個 Celery 任務

[英]Run multiple Celery tasks using a topic exchange

我正在用 Celery 替換一些本土代碼,但很難復制當前的行為。 我想要的行為如下:

  • 創建新用戶時,應使用user.created路由鍵將消息發布到tasks交換。
  • 此消息應觸發兩個 Celery 任務,即send_user_activate_emailcheck_spam

我嘗試通過使用ignore_result=True參數定義user_created任務以及send_user_activate_emailcheck_spam的任務來send_user_activate_email check_spam

在我的配置中,我添加了以下路由和隊列定義。 當消息傳遞到user_created隊列時,它不會傳遞到其他兩個隊列。

理想情況下,消息僅傳送到send_user_activate_emailcheck_spam隊列。 使用 vanilla RabbitMQ 時,消息被發布到一個交換器,隊列可以綁定到該交換器,但 Celery 似乎直接將消息傳遞到隊列。

我將如何在 Celery 中實現上述行為?

CELERY_QUEUES = {
    'user_created': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'},
    'send_user_activate_email': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'},
    'check_spam': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'},
}

CELERY_ROUTES = {
    'user_created': {
        'queue': 'user_created',
        'routing_key': 'user.created',
        'exchange': 'tasks',
        'exchange_type': 'topic',
    },
    'send_user_activate_email': {
        'queue': 'user_created',
        'routing_key': 'user.created',
        'exchange': 'tasks',
        'exchange_type': 'topic',
    },
    'check_spam': {
        'queue': 'user_created',
        'routing_key': 'user.created',
        'exchange': 'tasks',
        'exchange_type': 'topic',
    },
}

聽起來您希望單個消息觸發/被兩個隊列使用,但這不是 Celery 的工作方式。 Exchange 會將任務發布到符合條件的隊列,但是一旦它被消耗,其他隊列就會忽略該消息。 每個要觸發的任務都需要一條消息。

Celery 新用戶經常會混淆,因為在這個系統中“隊列”有兩種用途; Queue() 和文檔所引用的 Kombu 隊列,以及直接保存消息並由工作人員使用的 AMQP 隊列。 當我們發布到隊列時,我們想到的是 AMQP 的,這是不正確的。 (感謝回答鏈接如下)。

回到你的問題,如果我理解正確,當 user_created 被消耗時,你希望它產生兩個以上的任務; send_user_activate_email 和 check_spam。 此外,這些不應相互依賴; 它們可以在不同的機器上並行運行,不需要知道彼此的狀態。

在這種情況下,您希望 user_created “apply_async”這兩個新任務並返回。 這可以直接完成,或者您可以使用包含 check_spam 和 send_user_activate_email 的 Celery“組”來實現此目的。 該小組提供了一些不錯的速記,並為您的任務提供了一些結構,因此我個人會向您推薦這個方向。

#pseudocode
group(check_spam.s(... checkspam kwargs ...), send_user_activate_email.s(... active email kwargs ...)).apply_async()

此設置將創建四個消息; 一個用於您要執行的每個任務,另外一個用於 Group(),這本身就會產生結果。

在您的情況下,我不確定 Exchange 或 ignore_result 是否必要,但我需要查看任務代碼並更多地了解系統才能做出判斷。

http://docs.celeryproject.org/en/latest/userguide/canvas.html#groups http://celery.readthedocs.org/en/v2.2.6/userguide/routing.html#exchanges-queues-and-routing -keys 為什么 CELERY_ROUTES 有“隊列”和“路由密鑰”?

(如果我離開我會刪除/刪除答案......)

設計和解決問題的簡單方法是使用 Celery 工作流程。
但首先,我會更改您的隊列定義,為每個任務設置唯一的路由鍵,並使用“直接”值設置 exchange_type。

根據celery 文檔直接交換通過精確的路由鍵匹配,因此我們為所有自定義任務和消費者隊列設置相同的交換,並像下一個片段一樣映射 routing_key(用於任務)和 binding_key(用於隊列):

CELERY_QUEUES = {
    'user_created': {'binding_key':'user_created', 'exchange': 'tasks', 'exchange_type': 'direct'},
    'send_user_activate_email': {'binding_key':'send_user_activate_email', 'exchange': 'tasks', 'exchange_type': 'direct'},
    'check_spam': {'binding_key':'check_spam', 'exchange': 'tasks', 'exchange_type': 'direct'},
}

CELERY_ROUTES = {
    'user_created': {
        'queue': 'user_created',
        'routing_key': 'user_created',
        'exchange': 'tasks',
        'exchange_type': 'direct',
    },
    'send_user_activate_email': {
        'queue': 'send_user_activate_email',
        'routing_key': 'send_user_activate_email',
        'exchange': 'tasks',
        'exchange_type': 'direct',
    },
    'check_spam': {
        'queue': 'check_spam',
        'routing_key': 'check_spam',
        'exchange': 'tasks',
        'exchange_type': 'direct',
    },
}

完成此更改后,您需要對可用列表 ( http://docs.celeryproject.org/en/latest/userguide/canvas.html#the-primitives ) 使用正確的工作流程。 閱讀您的問題,我認為您需要一個鏈,因為需要保留順序。

sequential_tasks = []
sequential_tasks.append(user_created.s(**user_created_kwargs))
sequential_tasks.append(send_user_activate_email.s(**send_user_activate_email_kwargs))
sequential_tasks.append(check_spam.s(**check_spam_kwargs))
#you can add more tasks to the chain
chain(*sequential_tasks)()

Celery 將透明地處理與隊列相關的工作。

暫無
暫無

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

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