概要
Celery にはタスクのリトライ機能が標準で備わっています
基本はタスク内の raise に反応してリトライ処理が走ります
様々なオプションがあるので今回はオプションをいろいろと変更して挙動を確認してみました
環境
- macOS 10.15.5
- Python 3.8.3
- celery 4.4.4
リトライ処理を追加した普通のタスク
まずは普通にリトライ機能を追加しただけのタスクです
必須なのは bind=True
です
これを使うとタスク内で self が参照できるようになり、リトライする場合は self.retry()
をコールすることで同じタスクをリトライできるようになります
from celery import Celery
app = Celery('tasks', broker='redis://localhost', backend='redis://localhost')
@app.task(bind=True)
def add(self, x, y):
try:
return x + y
except Exception as exc:
self.retry(exc=exc)
特定の時間ウェイトしたあとにリトライする方法
default_retry_delay
を使います
単位は秒になります
from celery import Celery
app = Celery('tasks', broker='redis://localhost', backend='redis://localhost')
@app.task(bind=True, default_retry_delay=5)
def add(self, x, y):
try:
raise
return x + y
except Exception as exc:
self.retry(exc=exc)
サンプルは必ずリトライします
デフォルトだとリトライ回数は 3 回のようです
変更する場合には self.retry(exc=exc, max_retries=5)
こんな感じで retry の引数に指定できます
try, except を使わずにリトライさせる
タスクないで発生するエラーのクラスがわかっているのであればデコレータの引数でエラーを指定することで自動的にリトライさせることもできます
from celery import Celery
app = Celery('tasks', broker='redis://localhost', backend='redis://localhost')
@app.task(bind=True, default_retry_delay=5, autoretry_for=(Exception,), retry_kwargs={'max_retries': 5})
def add(self, x, y):
raise
return x + y
リトライの回数は retry_kwargs
を使って辞書形式でオプションを渡すことができます
exponential backoff を使う
指定の時間待ってリトライだと効率がよくない場合があります
その場合は exponential backoff の機能があるのでこれを使いましょう
簡単に言えば失敗するたびにウェイトする時間が増える仕組みのことです
@app.task(bind=True, autoretry_for=(Exception,), retry_kwargs={'max_retries': 5}, retry_backoff=True)
def add(self, x, y):
raise
return x + y
これで確認してみるとウェイトの時間が 0s -> 1s -> 2s -> 4s のように指数的に増えているのが確認できると思います
exponential backoff の場合回数ではなく時間でリトライ回数を指定することもできます
retry_backoff_max
を使います
デフォルトでは 600秒が指定されており 600秒間の間 exponential backoff でリトライを繰り返してくれます
ステータスはどうなっているか
リトライ中のタスクのステータスも一応確認してみました
flower を使っています
リトライが一度でも発生すると RETRY の状態になるようです
リトライ中だからと言って STARTED や PENDING にはならないようです
最後に
Celery のリトライ処理を試してみました
基本はリトライを実装したほうが良いと思いますが無駄なリトライなどが発生してタスクの完了が遅くならないように注意しましょう
0 件のコメント:
コメントを投稿