Technique

웹서비스 비동기(백그라운드) 프로세스 만들기 (feat. Django, Celery) 2

JAY-GO 2018. 4. 1. 21:59
반응형

 이번 포스팅에서는 앞에서 준비한 환경을 이용하여 Django 에서 Celery를 적용해 비동기 동작을 수행하는 웹어플리케이션을 만들어 보도록 하겠습니다.


 만들어볼 웹 어플리케이션을 통해 구현하고자 하는 기능은 아래와 같습니다.

 4개의 버튼에 각각 동기 , 동기-지연, 비동기, 비동기-지연 프로세스를 할당하고, 각가의 버튼의 프로세스 수행 결과를 표시한다.


 위에서 정의한 웹 어플리케이션을 아래와 같은 모습으로 구현해보고자 합니다.


1. 필요한 패키지 설치

 지금 docker로 실행중인 컨테이너에는 django를 nginx 서버로 구동하기 위한 최소한의 패키지만 깔려 있습니다. Celery 동작을 위해 필요한 Celery 및 rabbitmq를 설치 합니다.


 ㅇ Celery 설치

# pip3 install celery

Collecting celery

  Downloading celery-4.1.0-py2.py3-none-any.whl (400kB)

    100% |################################| 409kB 1.8MB/s

Requirement already satisfied: pytz>dev in /usr/local/lib/python3.6/dist-packages (from celery)

Collecting kombu<5.0,>=4.0.2 (from celery)

  Downloading kombu-4.1.0-py2.py3-none-any.whl (181kB)

    100% |################################| 184kB 3.0MB/s

Collecting billiard<3.6.0,>=3.5.0.2 (from celery)

  Downloading billiard-3.5.0.3-py3-none-any.whl (89kB)

    100% |################################| 92kB 3.7MB/s

Collecting amqp<3.0,>=2.1.4 (from kombu<5.0,>=4.0.2->celery)

  Downloading amqp-2.2.2-py2.py3-none-any.whl (48kB)

    100% |################################| 51kB 2.3MB/s

Collecting vine>=1.1.3 (from amqp<3.0,>=2.1.4->kombu<5.0,>=4.0.2->celery)

  Downloading vine-1.1.4-py2.py3-none-any.whl

Installing collected packages: vine, amqp, kombu, billiard, celery

Successfully installed amqp-2.2.2 billiard-3.5.0.3 celery-4.1.0 kombu-4.1.0 vine-1.1.4


 ㅇ apt-get update(패키지 리스트 업데이트)

   - 해당 명령어를 통해 설치 가능한 패키지 리스트 업데이트를 해야 정상적인 패키지 설치가 가능 합니다.

# apt-get update

Hit:1 http://security.ubuntu.com/ubuntu bionic-security InRelease

Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [235 kB]

Hit:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease

Hit:4 http://archive.ubuntu.com/ubuntu bionic-backports InRelease

Get:5 http://archive.ubuntu.com/ubuntu bionic/universe Sources [11.5 MB]

Get:6 http://archive.ubuntu.com/ubuntu bionic/main amd64 Packages [1341 kB]

Get:7 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [11.2 MB]

Get:8 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [185 kB]

Get:9 http://archive.ubuntu.com/ubuntu bionic/restricted amd64 Packages [13.3 kB]

Fetched 24.5 MB in 1min 28s (276 kB/s)

Reading package lists... Done


 ㅇ rabbitmq설치

# apt-get install rabbitmq-server

Reading package lists... Done

Building dependency tree

Reading state information... Done

The following additional packages will be installed:

  cron erlang-asn1 erlang-base erlang-corba erlang-crypto erlang-diameter erlang-edoc erlang-eldap erlang-erl-docgen erlang-eunit erlang-ic erlang-inets erlang-mnesia erlang-nox

  erlang-odbc erlang-os-mon erlang-parsetools erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssh erlang-ssl erlang-syntax-tools erlang-tools erlang-xmerl libc-bin libc-dev-bin

  libc6 libc6-dev libltdl7 libodbc1 libpopt0 libpython-stdlib libpython2.7-minimal libpython2.7-stdlib libsctp1 libssl1.1 logrotate python python-minimal python2.7 python2.7-minimal

Suggested packages:

  anacron checksecurity exim4 | postfix | mail-transport-agent erlang erlang-manpages erlang-doc xsltproc fop erlang-ic-java glibc-doc locales libmyodbc odbc-postgresql tdsodbc

  unixodbc-bin lksctp-tools bsd-mailx | mailx python-doc python-tk python2.7-doc binfmt-support

The following NEW packages will be installed:

  cron erlang-asn1 erlang-base erlang-corba erlang-crypto erlang-diameter erlang-edoc erlang-eldap erlang-erl-docgen erlang-eunit erlang-ic erlang-inets erlang-mnesia erlang-nox

  erlang-odbc erlang-os-mon erlang-parsetools erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssh erlang-ssl erlang-syntax-tools erlang-tools erlang-xmerl libltdl7 libodbc1

  libpopt0 libpython-stdlib libpython2.7-minimal libpython2.7-stdlib libsctp1 libssl1.1 logrotate python python-minimal python2.7 python2.7-minimal rabbitmq-server

The following packages will be upgraded:

  libc-bin libc-dev-bin libc6 libc6-dev

4 upgraded, 39 newly installed, 0 to remove and 162 not upgraded.

Need to get 35.8 MB of archives.

After this operation, 63.2 MB of additional disk space will be used.

Do you want to continue? [Y/n] y

Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libc6-dev amd64 2.27-0ubuntu2 [2591 kB]

Get:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 libc-dev-bin amd64 2.27-0ubuntu2 [71.8 kB]

...

...


2. Django 어플리케이션 작성

 이제 Django 어플리케이션을 만들어 봅시다. 앞에서 언급했듯이 개발을 위한 소스 작성은 윈도우 환경에서 수행하고, 어플리케이션은 Linux 환경에서 동작하도록 Docker의 Volume 기능을 이용해 셋팅되어 있습니다.(Docker를 이용한 Windows에서 Linux 개발환경 구축 (feat, Django) 참조)


 ㅇ django 앱생성

 호스트(윈도우) 환경에서이전 포스팅에서 준비한 Django 프로젝트에 어플리 케이션을 추가 합니다.

C:\Users\dev\PycharmProjects\docker_django_celery>python manage.py startapp applycelery

어플리케이션 디렉토리가 추가된 것을 확인할 수 있습니다.

 ㅇ settings.py에 생성된 앱 추가

 - 생성된 앱에 대하여 settings.py에 INSTALLED_APPS에 추가해 줘야 합니다.

<mywebapp/settings.py>

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'applycelery',
]


 ㅇ 모델 만들기

 우리가 정의한 어플리케이션을 위해서 필요한 모델을 만듭니다. 여기서는 사용자가 어떤 버튼을 클릭하였는지, 클릭한 시간과 동작이 종료된 시간이 언제인지, 그리고 그 차이가 얼마나 나는지에 대한 정보를 담기위해 아래와 같이 모델을 정의 합니다.

<applycelery/models.py>

from django.db import models

# Create your models here.
class operate_time(models.Model):

click_time = models.DateTimeField()
done_time = models.DateTimeField()
time_gap = models.DurationField()
click_command = models.CharField(max_length=20)

def __str__(self):
return self.click_command

 모델을 DB에 적용 할 수 있도록 migration을 수행합니다. 별도의 DB 셋팅을 하지 않았음으로 sqlite3 파일이 생성되어 DB로 활용됩니다.

C:\Users\dev\PycharmProjects\docker_django_celery>python manage.py makemigrations

C:\Users\dev\PycharmProjects\docker_django_celery>python manage.py migrate

 정의한 모델을 admin 페이지에서 사용할 수 있도록 admin.py 파일에 해당 모델을 추가합니다.

<applycelery/admin.py>

from django.contrib import admin
from .models import operate_time

# Register your models here.
admin.site.register(operate_time)

  /admin 페이지에 들어가기 위한 아이디를 만듭니다.

C:\Users\dev\PycharmProjects\docker_django_celery>python manage.py createsuperuser

Username (leave blank to use 'root'): applycelery

Email address:

Password:

Password (again):

Superuser created successfully.


 ㅇ view 만들기

 어플리케이션의 동작들을 정의 해 봅시다. 지금은 기본인 동기 프로세스에 대해서만 정의 하겠습니다.

from django.shortcuts import render
from .models import operate_time
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()

return render(request, 'django_celery_main.html', {'operate_list': operate_list})

 - 하나의 페이지에서 동작 함으로 하나의 뷰를 작성 하였습니다.

 - 동작 결과를 정의한 model을 db에서 뽑아 operate_list에 할당 합니다. 이를 template에 전달하여 웹 화면에 해당 내역들이 보여질 것입니다.

 - request.GET.get('operate') : http 요청이 get으로 들어올 때 operate라는 변수에 대한 값을 반환합니다. 여기서는 이를 통해 해당 변수명을 가진 버튼이 동작했는지 판별하는 용도로 사용하였습니다.

 - time.sleep(10) : 해당 프로세스를 10초간 정지 시킵니다. 이는 해당 if문이 실행후 긴 시간동안 특정 작업을 처리하고 있음을 표현하기 위해 사용되었습니다.


길어서 다음 포스팅에 계속....


반응형