Celeryのハマリポイント
はい、Celeryです。Celeryって本当によく使いますけど、本当に初見殺し多いですよね。今回はふとした気の迷いでそんなハマリポイントをいくつか羅列してみます。 (基本 django-celery を対象にしています)
ハマリポイント1 - MySQLがデッドロックして動作しなくなった
BlockerをMySQLにした時に起こります、公式ドキュメントにも書いてある有名なハマリポイント。
対策
- SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED をsession毎に発行
- my.confに書いてデフォルト設定
ハマリポイント2 - Task Resultsが消えない ##
いつもRabbitMQ、 RedisをBlockerにしてたんだけど、Databaseに変えた途端起こるハマリポイント。 CELERY_TASK_RESULT_EXPIRES設定しているのにおかしいなーとか思った人もいるはず。
対策
- celerybeatを起動しておく
- celery.task.backend_cleanup() をcronあたりで定期実行
- そもそも CELERY_IGNORE_RESULT で Task Resultを溜めない
ハマリポイント3 - 処理速度遅くね? ##
デフォルトだと遅いです。どれくらい遅いかは忘れたけど遅いです。
対策
- CELERY_DISABLE_RATE_LIMITS を設定
- CELERY_ANNOTATIONS = {'*': {'rate_limit': '2000/s'}} とかやっておく (OrderedDict)
- CELERYD_CONCURRENCY を増やす
- CELERYD_POOL を processes から 非同期ワーカー (gevent, eventletの癖を理解した上で) に変更してみる
ハマリポイント4 - エラー時にメールが飛ばないの... ##
エラーが起きてるのにCeleryがエラーメッセージを送ってくれない、死にたい。
対策
- CELERY_SEND_TASK_ERROR_EMAILS を設定
ハマりポイント5 - リトライ設定したいけど、項目多すぎてよくわからん。
対策
- CELERY_TASK_PUBLISH_RETRY_POLICY
ハマリポイント6 - max_retriesを設定しているのにリトライしない ##
対策
- task.retry() を呼んでください
ハマリポイント7 - 全ての回数のリトライ終了後に処理をかましたい ##
対策
- task.retry から celery.exceptions.MaxRetriesExceeded が投げられるのでそれを捕まえてください
ハマリポイント8 - Celeryのタイムアウト秒数を超えても、exceptionを投げてくれない
対策
- CELERYD_TASK_SOFT_TIME_LIMITを設定 CELERYD_TASK_TIME_LIMIT は使用しない
ハマリポイント9 - 非同期中、必要なデータがDatabaseにある筈なのにない
Database内の必要なデータがcommitされる前にtaskが起動されてしまってる事が多いです
これはCeleryが悪いわけじゃないですけど、同時接続数が多くなればまぁよくあります。
対策
- 愚直に非同期処理前にマニュアルでコミットを確定させる
- リトライを多めにとっておく, Countdownも指定しておく
最近、超忙しいのでここまでです。 TODO: 暇になったらまたかく