설치
celery 설치
$ pip install celery
RabbitMQ 서버 설치
$ sudo apt-get install rabbitmq-server
패키지를 설치하는 과정에서 우분투는rabbitmq
사용자와 rabbitmq
그룹을 추가한다.
RabbitMQ 서비스 시작 및 상태 확인
RabbitMQ 서비스를 아래와 같이 등록 구동한다.
$ sudo systemctl enable rabbitmq-server
$ sudo systemctl start rabbitmq-server
RabbitMQ 서비스의 구동 현황은 다음과 같이 확인할 수 있다.
systemctl status rabbitmq-server
Django 비동기 배치 작업 추가
guest
기본 사용자 제거 및 사용자 추가
RabbitMQ 서버 설치 시 디폴트 사용자 정보는 아래와 같다.
$ sudo rabbitmqctl list_users
Listing users ...
guest [administrator]
현재 [administrator]
태그 표시가 되어 있는 guest
사용자 하나가 기본으로 생성되어 있으며 권한은 다음과 같이 확인할 수 있다.
$ sudo rabbitmqctl list_user_permissions guest
Listing permissions for user "guest" ...
/ .* .* .*
먼저 새로운 사용자를 egg
이름으로 추가한다. PASSWORD
대신에 적당한 비밀번호를 같이 적어줘야 한다.
$ sudo rabbitmqctl add_user egg PASSWORD
Creating user "egg" ...
새로 만들어진 egg
사용자는 어떤 태그도 없는데 여기에 administrator
태그를 설정해주도록 하고 결과를 확인한다.
$ sudo rabbitmqctl list_users
Listing users ...
guest [administrator]
egg []
$ sudo rabbitmqctl set_user_tags egg administrator
Setting tags for user "egg" to [administrator] ...
$ sudo rabbitmqctl list_users
Listing users ...
guest [administrator]
egg [administrator]
새 사용자 egg
에게 모든 권한을 부여하고 권한 부여가 올바르게 되었는지 확인한다.
$ sudo rabbitmqctl set_permissions egg ".*" ".*" ".*"
Setting permissions for user "egg" in vhost "/" ...
$ sudo rabbitmqctl list_permissions
Listing permissions in vhost "/" ...
guest .* .* .*
egg .* .* .*
이제 guest
사용자를 삭제한다.
$ sudo rabbitmqctl delete_user guest
Deleting user "guest" ...
conf/settings.py
파일 수정
앞서 egg
사용자를 만들었으고 PASSWORD
비밀번호로 RabbitMQ 서비스에 접속하기 위해 아래와 같이 CELERY_BROKER_URL
값을 다음과 같이 설정한다.
CELERY_BROKER_URL = 'amqp://egg:PASSWORD@localhost:5672//'
conf/celery.py
파일 추가
Celery 앱을 생성하기 위해 conf/celery.py
파일을 아래와 같이 작성할 수 있다.
from celery import Celery
app = Celery(‘conf’)
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
Celery 매뉴얼에서는 위 코드에서 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "conf.settings.local")
같은 코드로 DJANGO_SETTINGS_MODULE
환경변수를 하드코딩으로 설정하게 되어 있는데 이 문서는 실행 시에 값을 넘겨주는 방법으로 설명한다.
conf/__init__.py
파일 수정
conf/__init__.py
파일을 수정하여 celery
모듈에서 app
을 가져오는데 그 이름을 celery_app
으로 한다.
from .celery import app as celery_app
__all__ = ['celery_app']
app/task.py
파일 추가
app/task.py
파일을 만들어서 비동기 배치 작업을 추가한다.
from celery import shared_task
@shared_task
def name_of_your_function(optional_param):
print('작업 시간이 오래 걸리는 일')
이제 비로소 시간이 오래 걸리는 작업을 기술한다.
app/views.py
파일 등에서 비동기 작업 호출
뷰 파일 등에서 이제 비동기 작업을 호출해야 하는데 아래와 같이 호출할 수 있다.
from .tasks import name_of_your_function
name_of_your_function.delay(5)
작업자(worker) 프로세스 시작
$ DJANGO_SETTINGS_MODULE='conf.settings.local' celery -A conf worker -l info
위와 같이 작업자 프로세스를 시작시킬 수 있는데 conf
대신에 알맞는 프로젝트 이름을 지정해야 한다.
그리고 DJANGO_SETTINGS_MODULE
환경변수도 올바로 선언해야 한다. 이와 같이 하는 이유는 테스트환경과 개발환경에서 서로 다른 환경을 가지기 때문이다.
우분투 운영 서버에서 worker 프로세스 관리
/var/www/com.example.www/conf/celery.conf
파일을 아래와 같은 내용으로 새로 만든다.
# 노드, 워커 개수 (보통은 하나):
CELERYD_NODES="worker1"
# 'celery' 명령어의 절대 경로 위치:
CELERY_BIN="/var/www/com.example.www/venv/bin/celery"
# 앱 인스턴스 (예: Proj)
CELERY_APP="conf"
# manage.py 호출 방법
CELERYD_MULTI="multi"
# 워커로 전달할 추가 명령어 옵션
CELERYD_OPTS="--time-limit=300 --concurrency=8"
# - %n 노드 이름의 첫 부분
# - %I 현재 자식 프로세스 인덱스
# prefork pool을 사용할 때 경쟁상태(race condition)을 피하기 위해 중요
CELERYD_PID_FILE="/var/www/com.example.www/run/celery-%n.pid"
CELERYD_LOG_FILE="/var/www/com.example.www/logs/celery-%n%I.log"
CELERYD_LOG_LEVEL="INFO"
/etc/systemd/system/celery.service
파일을 아래와 같은 내용으로 새로 만든다.
[Unit]
Description=Celery Worker
After=network.target
[Service]
Type=forking
User=egg
Group=developers
EnvironmentFile=/var/www/com.example.www/conf/celery.conf
WorkingDirectory=/var/www/com.example.www/repo
ExecStart=/bin/sh -c 'DJANGO_SETTINGS_MODULE=‘conf.settings.production' ${CELERY_BIN} multi start ${CELERYD_NODES} \
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
ExecStop=/bin/sh -c 'DJANGO_SETTINGS_MODULE=‘conf.settings.production' ${CELERY_BIN} multi stopwait ${CELERYD_NODES} \
--pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c 'DJANGO_SETTINGS_MODULE=‘conf.settings.production' ${CELERY_BIN} multi restart ${CELERYD_NODES} \
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
StandardError=syslog
[Install]
WantedBy=multi-user.target
아래와 같이 위 스크립트를 등록 하는데 Celery 매뉴얼과 다른 중요한 차이점은 DJANGO_SETTINGS_MODULE=conf.settings.production
과 같이 운영 환경에서 환경변수를 동적으로 정확히 지정해줘야 한다.
그리고 아래와 같이 데몬을 실행할 수 있다.
$ sudo systemctl enable celery
$ sudo systemctl start celery
위 명령어로 시작하기 전에 반드시 django 앱 및 celery 설정이 올바르게 되어 있어야 한다.
만약 celery.service
파일을 수정하고 재시작하려면 아래와 같이 명령한다.
$ sudo systemctl daemon-reload
$ sudo systemctl restart celery