3. Celery 셋팅
이번 포스팅에서는 앞에서 작성해 놓은 django 앱에 비동기 프로세스를 위한 Celery를 적용해 보도록 하겠습니다. 이에 필요한 celery와 rabbitmq 패키지는 앞선 포스팅에서 이미 설치 하였습니다.
ㅇ celery.py 생성
celery를 사용하기 위해서는 django프로젝트의 프로젝트 폴더에 celery.py를 추가해야 합니다.
<mywebapp/celery.py>
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mywebapp.settings')
app = Celery('applycelery')
# 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 registered Django app configs.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
- 우리는 docker에 필요한 패키지를 깔아두었기 때문에, 윈도우 환경인 ide환경에서는 celery의 import가 되지 않습니다. 경고 메시지가 떠도 걱정하지 않으셔도 됩니다.
- os.environ.setdefault()에 django프로젝트의 settings를 연결 합니다.
- app=Celery() 란에 앞에서 작성해둔 앱의 이름을 추가 하여 셀러리가 해당 앱에서 동작함을 정의합니다.
ㅇ __init__.py 수정
프로젝트 폴더의 __init__.py 에 필요한 내용을 추가 합니다.
<mywebapp/__init__.py>
from __future__ import absolute_import, unicode_literals
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ['celery_app']
ㅇ tasks.py 만들기
Celery를 통해 비동기로 동작할 Task(코드)들이 들어가는 파일 입니다. 아직은 공식 예제에 있는 기본 Task로 작성하였습니다. celery가 정상적으로 추가되었는지 확인 하고 필요한 코드를 작성해봅시다.
<applycelery/tasks.py>
# Create your tasks here
from __future__ import absolute_import, unicode_literals
from celery import shared_task
@shared_task
def add(x, y):
return x + y
@shared_task
def mul(x, y):
return x * y
@shared_task
def xsum(numbers):
return sum(numbers)
ㅇ Celery 작동 확인
지금까지 셋팅한 celery가 동작하는지 확인 해보겠습니다. docker 컨테이너의 콘솔(exec) 버튼 으로 컨테이너로 들어가서 celery를 구동하여 보겠습니다.
# celery -A mywebapp worker -l info
/usr/local/lib/python3.6/dist-packages/celery/platforms.py:795: RuntimeWarning: You're running the worker with superuser privileges: this is
absolutely not recommended!
Please specify a different user using the -u option.
User information: uid=0 euid=0 gid=0 egid=0
uid=uid, euid=euid, gid=gid, egid=egid,
-------------- celery@629b4d182cdc v4.1.0 (latentcall)
---- **** -----
--- * *** * -- Linux-4.4.89-boot2docker-x86_64-with-Ubuntu-18.04-bionic 2018-04-06 23:01:05
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: applycelery:0x7f282b6654a8
- ** ---------- .> transport: amqp://guest:**@localhost:5672//
- ** ---------- .> results: disabled://
- *** --- * --- .> concurrency: 1 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
[tasks]
. applycelery.tasks.add
. applycelery.tasks.mul
. applycelery.tasks.xsum
. mywebapp.celery.debug_task
정상적으로 셋팅이 완료 되었다면 위와같은 화면이 나타납니다. 이후 계속적으로 error 메시지가 작동 합니다. 이는 celery와 연동할 브로커인 rabbitmq를 동작시키지 않아 발생하는 메시지 입니다.
하단의 [tasks]를 오면 tasks.py에 작성해 놓은 task 들이 나타납니다. 정상적으로 celery가 동작하고 있음을 확인할 수 있습니다.
4. celery 적용
이제 4개의 버튼중 정의 안된 2개의 버튼에 들어갈 기능을 celery로 구현 해 봅시다.
ㅇ celery task 정의
celery에서 동작하는 task를 작성해 봅시다. 기본적으로 django view에 동작하는 코드와 유사하게 만들어 같은 코드가 동기로 동작하는 것과 비동기로 동작하는 것을 비교하고자 합니다.
앞에서 준비한 task.py를 수정 합니다.
<applycelery/task.py>
# Create your tasks here
from __future__ import absolute_import, unicode_literals
from celery import shared_task
from .models import operate_time
from django.utils import timezone
import time
@shared_task
def celery():
click_command = "celery"
click_time = timezone.now()
done_time = timezone.now()
time_gap = done_time - click_time
form_new = operate_time(click_time=click_time, done_time=done_time, time_gap=time_gap, click_command=click_command)
form_new.save()
@shared_task
def celery_delay():
click_command = "celery_delay"
click_time = timezone.now()
time.sleep(10)
done_time = timezone.now()
time_gap = done_time - click_time
form_new = operate_time(click_time=click_time, done_time=done_time, time_gap=time_gap, click_command=click_command)
form_new.save()
ㅇ view에 적용
위에서 작성한 celery task를 django view에 연결 해줍니다. 해당 task를 비동기로 사용하기 위해서는 .delay()로 동작 시켜야 합니다. 만약 이를 포함하지 않으면 보통의 함수 호출과 같이 동기식으로 동작하게 됩니다.
<applycelery/views.py>
from django.shortcuts import render
from .models import operate_time
from .tasks import celery, celery_delay
from django.utils import timezone
import time
# Create your views here.
def app_core(request):
operate_list = operate_time.objects.order_by('-id').all()
if (request.GET.get('operate')):
click_command = "operate"
click_time = timezone.now()
done_time = timezone.now()
time_gap = done_time-click_time
form_new = operate_time(click_time=click_time, done_time=done_time, time_gap=time_gap, click_command=click_command)
form_new.save()
if (request.GET.get('operate_delay')):
click_time = timezone.now()
time.sleep(10)
done_time = timezone.now()
time_gap = done_time-click_time
click_command = "operate"
form_new = operate_time(click_time=click_time, done_time=done_time, time_gap=time_gap, click_command=click_command)
form_new.save()
if (request.GET.get('celery')):
celery.delay()
if (request.GET.get('celery_delay')):
celery_delay.delay()
return render(request, 'django_celery_main.html', {'operate_list': operate_list})
tasks.py에 정의된 task 들을 import 하고 해당 조건문에서 .delay()로 호출 하였습니다.
이제 필요한 셋팅 및 코드 작성을 마쳤습니다. 다음 포스팅에서는 celery 및 기타 필요한 페키지들을 동작시켜 celery동작을 확인하고 celery에 의한 비동기 동작을 직접 경험해 보도록 하겠습니다.
'Technique' 카테고리의 다른 글
카카오톡 플러스친구를 이용한 email 간편 전송 서비스 만들기(feat, DJANGO, groomide) 1 (0) | 2018.09.04 |
---|---|
웹서비스 비동기(백그라운드) 프로세스 만들기 (feat. Django, Celery) 5 (0) | 2018.04.08 |
웹서비스 비동기(백그라운드) 프로세스 만들기 (feat. Django, Celery) 3 (0) | 2018.04.05 |
웹서비스 비동기(백그라운드) 프로세스 만들기 (feat. Django, Celery) 2 (0) | 2018.04.01 |
웹서비스 비동기(백그라운드) 프로세스 만들기 (feat. Django, Celery) 1 (0) | 2018.03.27 |