21

私はこれについて多くの調査を行ってきましたが、これに対する良い答えがまだどこにも見つかっていないことに驚いています。

Heroku で大規模なアプリケーションを実行しています。処理に非常に長い特定のセロリ タスクがあり、タスクの最後に結果を保存します。Heroku に再デプロイするたびに、SIGTERM (そして最終的には SIGKILL) が送信され、実行中のワーカーが強制終了されます。キューに入れられたタスクを失う代わりに、最終的に必要な結果を保存できるように、ワーカー インスタンスが正常にシャットダウンし、後で処理するためにキューに再登録する方法を見つけようとしています。

ワーカーに SIGTERM を適切にリッスンさせる方法が見つかりません。私が得た最も近いものは、python manage.py celeryd直接実行するときは機能しますが、フォアマンを使用してHerokuをエミュレートするときは機能しません。

@app.task(bind=True, max_retries=1)
def slow(self, x):
    try:
        for x in range(100):
            print 'x: ' + unicode(x)
            time.sleep(10)
    except exceptions.MaxRetriesExceededError:
        logger.error('whoa')
    except (exceptions.WorkerShutdown, exceptions.WorkerTerminate) as exc:
        logger.error(u'retrying, ' + unicode(exc))
        raise self.retry(exc=exc, countdown=10)
    except (KeyboardInterrupt, SystemExit) as exc:
        print 'retrying'
        raise self.retry(exc=exc, countdown=10)
    else:
        return x
    finally:
        logger.info('task ended!')

foreman 内で実行されているこのセロリ タスクを開始して Ctrl+C を押すと、次のようになります。

^CSIGINT received
22:20:59 system   | sending SIGTERM to all processes
22:20:59 web.1    | exited with code 0
22:21:04 system   | sending SIGKILL to all processes
Killed: 9

KeyboardInterruptしたがって、セロリの例外も、SystemExit他の投稿で見た例外も、SIGTERM を適切にキャッチしてワーカーをシャットダウンしないことは明らかです。

これを行う正しい方法は何ですか?

4

3 に答える 3

1

残念ながら、セロリはクリーンなシャットダウンを行うようには設計されていません。これまで。私は真剣です。セロリ ワーカーは SIGTERM に応答しますが、タスクが完了していない場合、ワーカー プロセスはタスクの完了を待ってから終了します。その場合、ワーカーが妥当な時間内にシャットダウンしない場合は SIGKILL を送信できますが、この場合、情報が失われます。つまり、どのジョブが未完了のままかがわからない場合があります。

于 2015-04-27T04:44:49.170 に答える