やったこと
Django・Celeryで非同期ジョブ実行の仕組みを実装した
背景
Django上でseleniumを使ってSBI証券の売買注文をする機能を実装したので、それをSlackからinteractiveコマンドを利用して実行させたくなった。
しかしslackのinteractiveコマンドでは3秒以内にレスポンスを返さないとエラーとなる仕様のため、時間がかかる作業はレスポンスだけ返して非同期で実行する必要があった。
そこでceleryを利用して、djangoで非同期ジョブを実行できるようにした。
環境
ubuntu 16.04
Python 3.5.2
Django 1.11.7
導入手順
1. redis導入
celeryでメッセージブローカとして利用するredisをサーバにインストールする
下記URLに従って実行
https://weblabo.oscasierra.net/redis-ubuntu1604-install-apt/
立ち上げも忘れずに
sudo service redis-server start
sudo systemctl enable redis-server
2. celery導入
pipでインストールする
pip install celery django-celery-results redis django-redis
一緒にインストールしたdjango-celery-resultsで非同期ジョブの実行結果をDBに保存できる
settings.py
下記の設定を追記する
# CELERY
CELERY_BROKER_URL = "redis://127.0.0.1:6379/1"
CELERY_RESULT_BACKEND = "django-db"
celery.py
settings.pyと同じ階層に新規作成する
environ
を用いて設定ファイルを使い分けているので、celery.pyでも同じように設定ファイルを読み込む
import os
from celery import Celery
import environ
env = environ.Env(DEBUG=(bool, False),) # set default values and casting
environ.Env.read_env('.env') # reading .env file
# set the default Django settings module for the 'celery' program.
settings = os.getenv(
"DJANGO_SETTINGS_MODULE", env("CELERY_ENVIRONMENT"))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings)
app = Celery('プロジェクト名')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registere
ジョブ定義
関数にデコレータ@app.task()
をつけると、ジョブとして実行できる。
seleniumでのSBI注文の実装は省略する。
下記のようにジョブ定義と実行のファイルを用意すれば良い
from プロジェクト名.celery import app
@app.task()
def add_numbers(a, b):
return a+b
from xxx.job import add_numbers
def execute()
add_numbers.delay(10, 3)
3. celery実行
サービスとして起動しておく
下記のサービスファイルを作成
[Unit]
Description=celery daemon
After=network.target
[Service]
User=furuya
Group=furuya
WorkingDirectory=[DjangoプロジェクトのPATH]
ExecStart=/home/furuya/.local/bin/celery -A プロジェクト名 worker --concurrency=1
[Install]
WantedBy=multi-user.target
下記を実行
sudo systemctl daemon-reload
sudo service celery start
sudo systemctl enable celery
celeryが動いていれば、非同期ジョブは順次実行されていく
4. 実行結果の確認
DjangoのAdmin画面で、実行結果を確認できる

各レコードへのリンク先で、パラメータ等の詳細も確認可能