python 기반의 서비스 운영 환경에서 참 많이 사랑받는 celery에 대해서 알아보자. (Broker는 redis를 사용)
분산 메시지 전달 기반 비동기 Task queue
루트 디렉토리: manage.py 가 존재하는 프로젝트 최상위 경로
프로젝트 디렉토리: wsgi.py가 존재하는 프로젝트 경로
pip install 'celery[redis]'
redis://:password@hostname:port/db_number
의 형식으로 지정# settings.py
# Redis
REDIS_HOST = os.getenv('REDIS_HOST')
REDIS_PORT = os.getenv('REDIS_PORT')
REDIS_PORT_SYSTEM = os.getenv('REDIS_PORT_SYSTEM')
REDIS_PW = os.getenv('REDIS_PW')
# Celery
CELERY_BROKER_URL = f'redis://:{REDIS_PW}@{REDIS_HOST}:{REDIS_PORT}'
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
# 루트디렉토리/프로젝트디렉토리/celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SQApi.settings')
app = Celery('app_name')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
# 루트디렉토리/프로젝트디렉토리/__init__.py
from .celery import app as celery_app
__all__ = ('celery_app',)
# <>/tasks.py
from celery import shared_task
@shared_task
def do_something(x, y):
...
return x + y
from apps.tasks import do_something
do_something.delay(5, 5)
celery -A SQApi worker -l INFO --autoscale 2,5
실 운영환경에서 효율적으로 Celery 워커를 동작시기키 위해서 daemon 서비스로 등록을 해서 사용하자
CELERYD_NODES="w1"
CELERY_BIN=가상환경내 Celery 파일
CELERY_APP="SQApi"
CELERYD_MULTI="multi"
CELERYD_OPTS="--concurrency=2 --autoscale=4,8"
CELERYD_PID_FILE="/home/ubuntu/logs/celery_%n.pid"
CELERYD_LOG_FILE="/home/ubuntu/logs/celery_%n%I.log"
CELERYD_LOG_LEVEL="INFO"
## /etc/systemd/system/celery.service
[Unit]
Description=Celery Service
After=network.target
[Service]
Type=forking
User=user name
Group=group name
EnvironmentFile=환경변수파일
WorkingDirectory=루트디렉토리
ExecStart=/bin/bash -c '${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/bash -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} \
--pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/bash -c '${CELERY_BIN} multi restart ${CELERYD_NODES} \
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable celery
sudo systemctl daemon-reload
sudo systemctl start celery
sudo systemctl status celery
ignore_result=True
설정을 하지 않을 경우, 결과가 필요 없음에도 브로커에 저장되어 불필요한 자원을 낭비할 수 있음
훌륭한 글 감사드립니다.