web-dev-qa-db-ja.com

指数関数的なバックオフでセロリのタスクを再試行する

このようなタスクの場合:

from celery.decorators import task

@task()
def add(x, y):
    if not x or not y:
        raise Exception("test error")
    return self.wait_until_server_responds(

それが例外をスローし、デーモン側からそれを再試行したい場合、指数バックオフアルゴリズムをどのように適用できますか、つまり2^2, 2^3,2^4など秒後に?

また、サーバー側から再試行が維持されるので、ワーカーが偶然に殺された場合、次に発生するワーカーが再試行タスクを実行しますか?

62
Quintin Par

task.request.retries 属性にはこれまでの試行回数が含まれているため、これを使用して指数バックオフを実装できます。

from celery.task import task

@task(bind=True, max_retries=3)
def update_status(self, auth, status):
    try:
        Twitter(auth).update_status(status)
    except Twitter.WhaleFail as exc:
        self.retry(exc=exc, countdown=2 ** self.request.retries)

Thundering Herd Problem を防ぐには、指数バックオフにランダムジッターを追加することを検討してください。

import random
self.retry(exc=exc, countdown=int(random.uniform(2, 4) ** self.request.retries))
121
asksol

Celery 4.2では、指数バックオフを自動的に使用するようにタスクを構成できます。 http://docs.celeryproject.org/en/master/userguide/tasks.html#automatic-retry-for-known-exceptions

@app.task(autoretry_for=(Exception,), retry_backoff=2)
def add(x, y):
    ...

(これはすでにCelery 4.1のドキュメントに含まれていましたが、実際にはリリースされていませんでした。 マージ要求 を参照してください)

22