« ^ »

Django + CeleryでブローカーにSSL有りのRedisを使う

所要時間: 約 4分

TL;DR

  • Celeryのデフォルトの設定ではCeleryでブローカーにSSL有りのRedisを使えない。
  • SSL有りのRedisを使うには次の設定が必要となる。
  • BROKER_USE_SSL: ブローカーとの接続とSSL設定のSSL使用を切り替える。例: {'ssl_cert_reqs': 'none'}
  • CELERY_REDIS_BACKEND_USE_SSL: Redisがブローカーの場合はこの設定も必要。例: {'ssl_cert_reqs': ssl.CERT_CERT_REQUIRED} (sslは標準ライブラリのssl)
  • Django + Celeryの設定例を記載した。


この記事は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を指定する。

環境

対象バージョン
OSmacOS 10.12.4
PythonPython3.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`