Python製の非同期ジョブフレームワークであるCeleryのワーカープロセスには 4種類のプールがある。それぞれに挙動の違いと長短がある。

プール

prefork

標準ライブラリであるmultiprocessingをベースに実装されており、タスクの 処理を行うプロセスを子プロセスとしてforkする。別のプロセスとして動作す るためGILの制約を受けない。そのためCPUバウンドの処理を複数のワーカーで 行う場合にパフォーマンスを発揮する。親プロセスがシグナルとしてTERMを受 け取った場合は、親プロセスは子プロセスで実行中のタスクの完了後に終了す る。

prefork: celery -A main.app worker --pool prefork --concurrency 1

eventlet

サードパーティライブラリであるeventletをベースに実装されており、タスク の処理をeventletベースのGreenletプールによって実行する。同一プロセス内 での実行のためGILの制約を受ける。IOバウンドの処理を複数のワーカーで行 う場合にパフォーマンスを発揮する。シグナルとしてTERMを受け取った場合は、 実行中のタスクの完了後に終了する。

eventlet: EVENTLET_HUB=poll celery -A main.app worker --pool eventlet --concurrency 1

macOS 11.2.3, Python3.9, eventlet-0.30.2で動作を行ったところ EVENTLET_HUB=poll の設定を行わないと起動時にエラーが発生した。

gevent

サードパーティライブラリであるgeventをベースに実装されており、タスクの 処理をgeventベースのGreenletプールによって実行する。同一プロセス内での 実行のためGILの制約を受ける。IOバウンドの処理を複数のワーカーで行う場 合にパフォーマンスを発揮する。シグナルとしてTERMを受け取った場合は、実 行中のタスクの完了後に終了する。

gevent: celery -A main.app worker --pool gevent --concurrency 1

solo

ワーカープロセスが直接タスクを処理する。メインループでタスクを処理しコ ンテキストスイッチがないため、CPUバウンドでの処理にパフォーマンスを発 揮する可能性がある。また子プロセスやスレッドのような機構を使わないため ワーカープロセス数がそのままワーカー数となりマイクロサービスなどの環境 下においては管理がシンプルになる。シグナルとしてTERMを受け取った場合は、 実行中のタスクの完了を待たず即座に終了する。

celery -A main.app worker --pool solo

シグナル

ワーカープロセスにシグナルを送ることで、終了の仕方やダンプなどの挙動を指示できる。

シグナル挙動
TERMタスクの完了を待ってシャットダウンする。
QUIT即座にシャットダウンする。
USR1ダンプを出力する。
USR2リモートデバッグの待受を開始する。