簡體   English   中英

芹菜redis后端並不總是返回結果

[英]Celery redis backend not always returning result

我正在經營芹菜工人,以便:

 -------------- celery@ v3.1.23 (Cipater)
---- **** ----- 
--- * ***  * -- Linux-4.4.0-31-generic-x86_64-with-debian-stretch-sid
-- * - **** --- 
- ** ---------- [config]
- ** ---------- .> app:         __main__:0x7fe76cd42400
- ** ---------- .> transport:   amqp://
- ** ---------- .> results:     redis://
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- 
--- ***** ----- [queues]
 -------------- .> celery           exchange=celery(direct) key=celery
[tasks]
  . tasks.mytask

tasks.py

@celery_app.task(bind=True, ignore_result=False)
def mytask(task):
    r = redis.StrictRedis()
    r.rpush('/task_finished', task.request.id)
    return {'result': 42}

當我嘗試運行以下代碼,並且一個接一個地運行2個任務時,它在獲取第一個結果但未能返回第二個結果時起作用。

import celery.result
import redis

r = redis.StrictRedis()
celery_app = Celery(name="my_long_task", backend="redis://")

while True:
    _, resp = r.blpop('/task_finished')
    task_id = resp.decode('utf-8')
    task = celery.result.AsyncResult(task_id, app=celery_app)
    print(task)
    print(task.result)

將返回:

第一循環

[1] 990e2d04-5664-4d7c-8a5c-e9cb4ef45e24  
[2] {'result': 42}

第二個循環 (無法返回結果):

[3] 8463cc46-0884-4bf7-b838-f0614f74b271  
[4] {}

但是如果我在while循環中實例化celery_app = Celery(name="my_long_task", backend="redis://") ,它每次都會工作。
沒有重新celery_app什么問題? 我錯過了什么?

編輯:

等待結果(在延遲的情況下)也不會起作用

while True:
    _, resp = r.blpop('/task_finished')
    task_id = resp.decode('utf-8')
    for i in range(0, 20):
        # Won't work because I need to re instantiate celery_app
        task = celery.result.AsyncResult(task_id, app=celery_app)
        print(task.result)
        time.sleep(1)

你有競爭條件。 這是發生的事情:

  1. 循環到達_, resp = r.blpop('/task_finished')並在那里阻塞。

  2. 該任務執行r.rpush('/task_finished', task.request.id)

  3. 循環解除task = celery.result.AsyncResult(task_id, app=celery_app) ,執行task = celery.result.AsyncResult(task_id, app=celery_app)並獲得一個空結果,因為該任務尚未將其結果記錄到數據庫中。

芹菜將結果提交給后端r.rpush可能有一種方法。 也許創建一個派生自Task的自定義類就可以了。 但這不是我嘗試過的。

但是,您當然可以修改代碼以將結果與任務ID 一起存儲。 就像是:

r.rpush('/task_finished', json.dumps({ "task_id": task.request.id, "result": 42 }))

為了說明,我使用了JSON序列化。 你可以使用你想要的任何方案。 閱讀時:

_, resp = r.blpop('/task_finished')
resp = json.loads(resp)

有了這個,您可能希望將ignore_result=False更改為ignore_result=True

暫無
暫無

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

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