この記事はDjango Advent Calendar 2017及びしむどん Advent Calendar 20171日目の記事です。またその後、記事を移転した。
CeleryのブローカーとしてSSL有りのRedisを使うための方法とDjango + Celeryでの設定例を紹介する。
背景
Azure Redis Cacheをスタンダードプランで使う場合、グローバルIPを割り振らなければアクセスできない。パスワードの設定などを行って使用することになるのだが、SSLも有効にする必要がある。このSSL有りのRedisをCeleryのブローカーに指定すると、Celeryのデフォルトの設定ではブローカーとの接続時にエラーする。Celeryのドキュメントには当然記述はあるが、Celeryの設定項目はとてもたくさんあり、わかりづらい。また解説自体が機能の説明になっているため、どのように使えばいいのか把握しづらい。そこで今回は、使用するシーンとしてDjango + Celeryの組み合わせで使う場合を想定し、動作するサンプルコードを実装した。その中でCeleryのブローカーにSSL有りRedisを指定する。
環境
対象 | バージョン |
---|---|
OS | macOS 10.12.4 |
Python | Python3.6.2 |
依存ライブラリ | requirementsを参照 |
requirements
実行には以下のライブラリを使用した。
Djangoプロジェクトの作成
Djangoプロジェクトを作成する。プロジェクト名はprojにした。
django-admin startproject proj .
celeryconfig.py
celeryconfig.py には Celeryの設定を記述する。まずはブローカーと、返却値をを保持しておくためのバックエンド、データの受け渡し時に用いる形式を指定する。これらはCeleryをつかう場合には必ず必要になる。ここで使用しているcustom_settingsは設定のためのヘルパーライブラリ。詳しくは https://pypi.python.org/pypi/custom_settings を参照。またSSL接続のための設定としてBROKER_USE_SSLとCELERY_REDIS_BACKEND_USE_SSLを設定する。
import custom_settings
custom = custom_settings.load('settings_custom')
BROKER_URL = custom.get('BROKER_URL', default='redis://:REDIS_PASS@localhost:6379/0')
CELERY_RESULT_BACKEND = custom.get('BROKER_URL', default='redis://:REDIS_PASS@localhost:6379/0')
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
import ssl
BROKER_USE_SSL = {'ssl_cert_reqs': 'none'}
CELERY_REDIS_BACKEND_USE_SSL = {'ssl_cert_reqs': ssl.CERT_REQUIRED}
Celeryの準備
先ほど作成したprojプロジェクトでCeleryを使えるようにしていく。まずは `proj/celery_.py` を作成し、Celeryオブジェクトを生成して設定をする。
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "proj.settings")
app = Celery("proj")
app.config_from_object("celeryconfig")
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task
def debug():
print("OK")
app.config_from_object(’celeryconfig')
で設定を読み込んでいる。今回はCeleryの設定は `celeryconfig.py` に記述した。Djangoの場合は `proj/settings.py` に同様の設定をして、 `app.config_from_obj('celeryconfig')` の第一引数を `'django.conf:settings'` にしても設定を読み込むことができる。また検証用にタスクを一つ定義した。このタスクは後ほど `celery call` コマンドで呼び出す。
動作確認
実行する環境を作成する。venvなどの記述はここでは割愛する。
依存ライブラリをインストールする。
pip install -r requirements.txt
サンプルコードはDjangoプロジェクトなのでマイグレーションを実行する。
python manage.py makemigrations
python manage.py migrate
Celeryワーカーを起動する。ワーカー起動は `-D` を付けているのでバックグラウンド実行となる。 `–logfile` で指定したファイルにログを出力する。
celery -A proj.celery_app worker -D --pidfile .worker.pid --logfile worker.log
proj.celery_.debug
をデバッグ用のタスクとして実装したため、このタスクを実行する。
celery -A proj.celery_app call proj.celery_.debug
次のようなハッシュ値が表示される。これはタスクがRedisに登録されてWorkerでの処理が終了した状態だ。
b77a6165-4458-4540-a3a7-0824f4d6ca30
もしハッシュ値が表示されない場合はどこかにおかしな箇所があるはずだ。特に次の項目を確認すると、問題を見付けられるかもしれない。
- Redisは起動しているか?
- Redisへの接続情報は間違っていないか?
- 設定ファイルの記述は正しいか?
後片付け
ワーカーがまだ起動したままなので停止する。ワーカーの起動時に `–pidfile` で指定したファイルにPIDが出力されている。そのプロセスをkillコマンドでkillする。
kill `cat .worker.pid`