들어가기 전에
동기 vs 비동기
(이미치 출처 : http://ojava.tistory.com/17)
어떤 서비스에 회원가입을 하면 메일이 날라오는 경우가 있다.
동기 : 메일이 날라올 때까지 아무것도 하지 못한다.
비동기 : 메일이 날라오지 않더라도 다른 작업을 할 수 있다.
비동기 방식이 짱짱맨 아니냐 하겠지만 어떤 방식이건 간에 장단점이 존재한다. 아무튼, 회원가입 축하 이메일 발송은 사실 고객(client)에게 중요한 부분이 아니다. 일단 가입을 하고 서비스를 이용하기를 원할 것이다. 이러한 이메일 발송은 비동기
처리로 보낼 수 있다. 이를 백그라운드
에 보낸다고 표현한다.
Djnago + Celery + Redis
Celery
는 일꾼이다. 해야 할 일들을 처리한다.
Reids
는 주인이다. 메시지 브로커를 담당한다.
Celery란?
Celery
는 안 보이는 곳에서 열심히 일하는 (백그라운드)일꾼이다. 처리해야 할 일을 Queue
로 쌓아둔다.큐(queue)에 쌓인 일을 일꾼들이 가져다가 열심히 일을한다. 파이썬 언어로 작성되어 있다.
Redis란?
Redis
는 실제 컴퓨터 메모리를 이용한 캐쉬다. Key
와 Value
값을 이용해 처리할 작업을 Celery
에게 보낸 다음 캐쉬 시스템에서 해당 키를 없애는 방식으로 동작한다.
좋은 점은 로컬과 DB사이에서 자료가 왔다갔다 하는 것보다 메모리에서 캐쉬를 가져다 쓰는 것이 훨씬 빠르다는 것이다. 따라서 특정 데이터를 반복적으로 돌려줘야 한다면 메모리 캐쉬를 사용하면 좋다.
설치할 때 주의점
Celery
는 파이썬 언어로 작성되어 있기 때문에 가상환경 위에서 pip
를 이용해 설치한다.
Redis
는 인 메모리를 이용한다고 했었다. 따라서 wget
으로 설치한다.
1. 설치하기
1-1 Celery 설치하기
$ pip install 'celery[redis]'
pip를 이용해 cerlry 모듈과 redis와의 연동을 위한 dependency를 한 번에 설치한다. redis
를 설치하지 않아도 일단 의존성 패키지는 설치 된다. 작은 따옴표('')를 꼭 붙여줘야 설치가 된다.
설치를 한뒤 pip list
로 확인하면 amqp, billiard, celery, kombu, redis, vine 등이 함꼐 설치된다(나도 처음 알았다).
Celery는 수행할 작업(task) 및 실행을 의뢰받을 브로커(AMQP, Redis)를 정의한다.
1-2 Redis 설치하기
$ wget http://download.redis.io/redis-stable.tar.gz$ tar xvzf redis-stable.tar.gz$ cd redis-stable$ make
$ redis-server # redis 실행$ redis-cli ping # 정상 설치되었는지 확인> PONG
PONG
메시지를 띄우면 설치 성공이다.
2. Django와 연동하기
디렉토리 구조
프로젝트 루트 폴더(project root folder) : celery
(장고 프로젝트를 담는 최상위 폴더)
프로젝트 폴더(project folder) : django_app
(여러 앱들로 구성되는 장고 프로젝트 폴더)
프로젝트 환경설정 폴더(project settings folder) : config
[프로젝트 폴더] / [환경설정 폴더] / __init__.py
from .tasks import app as celery_app__all__ =
[프로젝트 폴더] / [환경설정 폴더] / settings.py
BROKER_URL = 'redis://localhost:6379/0'CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
[프로젝트 폴더] / [환경설정 폴더] / tasks.py(파일 추가)
import osfrom celery import Celery# `celery` 프로그램을 작동시키기 위한 기본 장고 세팅 값을 정한다.app =# namespace='CELERY'는 모든 셀러리 관련 구성 키를 의미한다. 반드시 CELERY라는 접두사로 시작해야 한다.# 장고 app config에 등록된 모든 taks 모듈을 불러온다.return x + y
3. Celery + Redis 실행시켜보기
실행하기
주의점 : 프로젝트 폴더에 진입한 뒤! 쉘에서 다음 명령을 입력해야 한다.
$ celery - worker --loglevel=info$ cerlry -A config worker --loglevel=info
실행 결과
➜ django_app celery -A config worker --loglevel=info-------------- celery@chulgyoo-15ZD960-GX30K v4.0.2---- **** -------- * *** * -- Linux-4.8.0-58-generic-x86_64-with-debian-stretch-sid 2017-07-15 05:53:49-- * - **** ---- ** ----------- ** ---------- .> app: config:0x7f5380456358- ** ---------- .> transport: redis://localhost:6379//- ** ---------- .> results: redis://localhost:6379/- *** --- * --- .> concurrency: 4-- ******* ---- .> task events: OFF--- ***** -------------------.> celery exchange=celery key=celery. config.tasks.add # [tasks]를 통해서 비동기로 작업 할 수 있는 목록들이 나온다. 현재는 add 하나.Connected to redis://localhost:6379//mingle: searching for neighborsmingle: all alone/home/chulgyoo/.pyenv/versions/3.6.1/envs/django_ev/lib/python3.6/site-packages/celery/fixups/django.py:202: UserWarning: Using settings.DEBUG leads to a memory leak, never use this setting in production environments!warnings.warncelery@chulgyoo-15ZD960-GX30K ready.
Debug(로컬)에서 실행하면 메모리
오류가 발생한다면
Cannot connet
문제
BROKER_URL 또는 RESULT_BACKEND를 잘못 지정해줬을 가능성이 있다.No moule named '[모듈이름]'
모듈 이름을 잘못 임포트 했다. 프로젝트 폴더 안에서 명령어를 실행한게 맞는지, 내가 만든 파일 이름이 맞는지 확인해야 한다.
4. Celery를 이용한 작업처리하기
작업을 실행시켜보자
Celery
를 실행시킨 상태에서 터미널을 하나 더 켠 뒤, 작업을 진행해보자. 위와 같이 있으면 된다.
$ python shell>>> from config.tasks import add>>> result =>>> result =>>> result =>>> result =>>> result =
5번을 실행시킨 뒤, Celery Shell을 확인해보면 Received task
라는 메시지와 함께 작업시간을 확인할 수 있다. 간단한 계산이기 때문에 많은 시간이 걸리지 않는다.
5. Celery WorkFlow
@app.task
로 처리하고 싶은 일에 딱지를 붙인다.add
작업에delay
를 붙이면Redis Backend
에 기록이 저장된다.Redis
는Celery
에게 일을 준다.일을 받은
Celery
는add
작업을 시작한다.
Redis
Redis는 아무래도 In-memory를 사용하는 것이 포인트다.
Celery는 파이썬 언어로 건드려볼 수 있지만, Redis는 간단한 편(?)이다.
설치
$ wget http://download.redis.io/redis-stable.tar.gz$ tar xvzf redis-stable.tar.gz$ cd redis-stable$ make
서버 시작
$ redis-server
서버 확인
$ redis-cli127.0.0.1:6379 > pingPONG
get, set 명령어 실행
서두에서 key
와 value
값으로 작업을 Celery
에게 보낸다고 언급했었다.
127.0.0.1:6379 > set mykey "myvalue"OK127.0.0.1:6379 > get mykey"myvalue"
서버 정지
$ redis-cli shutdown
참고한 글
Celery + Redis
http://dgkim5360.tistory.com/entry/python-celery-asynchronous-system-with-redisCelery + Redis 연동에 관한 전반적인 정보를 얻었습니다.