Help us understand the problem. What is going on with this article?

CeleryをDjangoで動かす

More than 1 year has passed since last update.

やったこと

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

下記の設定を追記する

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でも同じように設定ファイルを読み込む

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注文の実装は省略する。
下記のようにジョブ定義と実行のファイルを用意すれば良い

job.py
from プロジェクト名.celery import app

@app.task()
def add_numbers(a, b):
    return a+b
execute.py
from xxx.job import add_numbers

def execute()
    add_numbers.delay(10, 3) 

3. celery実行

サービスとして起動しておく

下記のサービスファイルを作成

/etc/systemd/system/celery.service
[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画面で、実行結果を確認できる

スクリーンショット 2019-05-05 16.07.01.png

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

tfuruya
Work:2017年入社。Python, Djangoで開発中。nginx, postgre。 Private:GoogleとSlack。Django,Pythonは勉強も兼ねて。Google Apps Scriptで色々連携させたい。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away