celery とは
セロリ。python job queue 処理のフレームワーク。worker daemon を待機させて async 処理の仕組みを作ったり、beat daemon を起動して定時バッチ処理を組んだりする。ドキュメントはよく整備されている。
- RDBよりも効率よく
- backend は rabbitmq cluster や redis cluster を使う。RDB 使えるけど使わないのが best practice
- job の流量制御は変更しやすいようにと考えられている
- worker daemon 起動。一台に複数起動してもよし。クラスター分散させて起動してもよし。
- job 依頼側と受け手側の両方が python で共通ライブラリ使うとかだと、どんぴしゃ
処理フロー的には AWS lambda や IBM bluemix OpenWhisk みたいな処理部分に、タスクスケジューラがついたものと考えても近い。API 定義とか気にせず処理分割を進められるのはありがたい。
worker
async job を使いたい場合は、worker daemon を起動させる。
celery -A proj worker
でデーモン起動させるのだけど、proj の指定方法がわかりにくい!
ざっくりルールはこんな感じ。
- カレントディレクトリと module 検索パスを検査対象として、Celery instance を探す
-
proj
の文字列中に:
があるとmodname:varname
が Celery instance に違いない -
proj.app
がモジュールでなければ Celery instance に違いない(おいおい) -
proj.celery
がモジュールでなければ Celery instance に違いない(うーむ) -
proj.celery
がモジュールなら-
proj.celery.app
がモジュールでなければ Celery instance に違いない(おいおい) -
proj.celery.celery
がモジュールでなければ Celery instance に違いない(うーむ) -
proj.celery
内の変数に Celery のサブクラスインスタンスが無いか調べる
-
-
proj
内の変数に Celery のサブクラスインスタンスが無いか調べる
つまり例示すると…
- カレントディレクトリにある
somename.py
ファイルに
Celery instance の変数 x が存在する場合-
celery -A somename:x worker
で起動する。あるいは -
celery -A somename worker
でも起動できる。
-
- カレントディレクトリから見て
somename/__init__.py
ファイルに
Celery instance の変数 x が存在すれば-
celery -A somename worker:x
で起動する。あるいは -
celery -A somename worker
でも起動できる。
-
- カレントディレクトリから見て
somename/__init__.py
が存在し、
somename/celery.py
ファイルに Celery instance の変数 x が存在すれば-
celery -A somename.celery:x worker
で起動する。あるいは -
celery -A somename.celery worker
で起動する。あるいは -
celery -A somename worker
で起動する。 -
from __future__ import absolute_import
を使うべし(python 2)
-
- カレントディレクトリから見て
somename/__init__.py
が存在し、
somename/subname.py
ファイルに Celery instance の変数 x が存在すれば-
celery -A somename.subname:x worker
で起動する。あるいは -
celery -A somename.subname worker
で起動する。
-
- モジュール検索パスの
somename
のモジュールにapp
変数が存在すれば、それを Celery instance だと思い込む。-
celery -A somename:app worker
で起動する。 -
celery -A somename worker
で起動する。
-
- モジュール検索パスの
somename
のモジュールに Celery instance の変数 x が存在すれば-
celery -A somename:x worker
で起動する。 -
celery -A somename worker
で起動する。
-
- モジュール検索パスの
somename.celery
がロードできて、その中に Celery instance の変数 x が存在すれば-
celery -A somename.celery:x worker
で起動する -
celery -A somename.celery worker
で起動する。 -
celery -A somename worker
で起動する。 -
from __future__ import absolute_import
を使うべし(python 2)
-
注意深く見ていると、パターンによって app の表示が少し変わる。
celery -A somename worker
...
- ** ---------- [config]
- ** ---------- .> app: __main__:0x106a950
celery -A somename worker
...
- ** ---------- [config]
- ** ---------- .> app: somename:0x1585410
ややこしい元凶は proj.app
と proj.celery
という特殊ルール。
極端にややこしいケースは Flask のドキュメント で説明がないところ。Flask は一般的には Flask instance な app
変数を作る。ところが celery も app
変数が見つかればCelery instance に違いないと思い込むので、食い違いが起こる。
回避策は例えばこのようになる:
- Flask instance の変数名を
app
以外にする -
:
付きの文字列で指定するcelery -A your_application:celery worker
beat
定時 batch を組みたいときは beat な daemon を起動させる。
celery -A somename beat
worker daemon とは別に起動させる。こちらは基本的にはスケールアウトしないので、注意して使わないといけない。
スケジュールの設定もプログラムには埋め込めず、基本設定ファイルに列挙することになるのも注意。
ところで
job queue とセロリの関係がよくわからない…そういうイメージなの…?
追記 : 今なら kafka + faust という選択肢もありますぞ。