Celery 란?
비동기적으로 처리해야할 일들을 수행하기 위해 Celery를 설치했다. 실시간 서비스를 제공하기 위해 꼭 필요한 작업이다.
Celery는 비동기적으로 작업을 처리하고 응답을 하게 해주는 파이썬 프레임워크이다. 이런 프레임워크를 works라고 부른다.
celery-beat
사용자의 요청이 시간이 오래 걸리는 경우나 다른 시스템과 연동되어 그 시스템에서 응답이 올때까지 대기해야 되는 경우에 주로 사용하게 된다. 이 외에도 주기적으로 어떤 통계를 도출해 낸단더지 하는 배치(일괄 처리)작업이 필요한 경우가 종종 생기는데 이때 Celery를 이용할 수 있다. 작업큐에 주기적으로 필요한 작업들을 넣어주면 되는데 이 역할을 하는것이 Celery에 포함된 beat이다.
celery 작업을 하기 위해서는 브로커를 설정한다. 브로커는 워커인 celery를 사용하기 위해서 작업 요청을 받는 큐라고 할 수 있는데 요청을 받아서 worker에게 적절히 분배하는 작업을 수행한다.
1. Celery와 Redis 설치
pip를 이용해 cerlry 모듈과 redis와의 연동을 위한 dependency를 한 번에 설치한다. redis를 설치하지 않아도 일단 의존성 패키지는 설치 된다. 작은 따옴표('')를 꼭 붙여줘야 설치가 된다.
$ pip install 'celery[redis]'
1 2 3 4 | $ wget http://download.redis.io/redis-stable.tar.gz $ tar xvzf redis-stable.tar.gz $ cd redis-stable $ make | cs |
make, make test, make install 을 실행
*** make test를 하던 중,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $ make test cd src && make test make[1]: Entering directory `/home/inyoung/redis-stable/src' You need tcl 8.5 or newer in order to run the Redis test make[1]: *** [test] 오류 1 make[1]: Leaving directory `/home/inyoung/redis-stable/src' make: *** [test] 오류 2 | cs |
You need tcl 8.5 or newer in order to run the Redis test 라는 오류가 발생 -> tcl을 설치해주었다.
$ yum -y
install
tcl
그리고 나서 make, make test, make install 해주면 설치 끝!
2. redis 잘 설치되어있는지 확인
redis-server # server 켜진 상태
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | $ redis-server 3780:C 31 Jan 11:22:49.406 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 3780:C 31 Jan 11:22:49.406 # Redis version=4.0.7, bits=64, commit=00000000, modified=0, pid=3780, just started 3780:C 31 Jan 11:22:49.406 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 3780:M 31 Jan 11:22:49.407 # You requested maxclients of 10000 requiring at least 10032 max file descriptors. 3780:M 31 Jan 11:22:49.407 # Server can't set maximum open files to 10032 because of OS error: Operation not permitted. 3780:M 31 Jan 11:22:49.407 # Current maximum open files is 4096. maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n'. _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 4.0.7 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 3780 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 3780:M 31 Jan 11:22:49.409 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. | cs |
* redis-server가 켜진 상태에서,
redis-cli ping # ping 했을 때 PONG 찍히면 성공
3. Django project에 celery와 redis를 추가
1. Celery와 Redis를 virtualenv 에 설치
1 2 3 4 | pip install celery pip install redis pip install django-celery-beat pip install django-celery-results | cs |
2. Django 프로젝트의 settings.py 수정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_celery_beat', 'django_celery_results', 'scraper', ] # Celery CELERY_BROKER_URL = 'redis://localhost:6379' CELERY_RESULT_BACKEND = 'redis://localhost:6379' CELERY_ACCEPT_CONTENT = ['application/json'] CELERY_TAST_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_TIMEZONE = 'Asia/Seoul' #Celery beat가 스케줄러이기 때문에 시간에 대한 정의를 해야함 | cs |
3. Celery App을 설정하기 위해서 celery.py 를 생성한다.
** 프로젝트 설정하는 폴더에 생성해야함. settings.py가 있는 [프로젝트명] - [프로젝트명] 폴더
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from __future__ import absolute_import import os from celery import Celery # Django의 세팅 모듈을 Celery의 기본으로 사용하도록 등록합니다. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'inyoung_scrap_prj.settings') app = Celery('inyoung_scrap_prj') # 문자열로 등록한 이유는 Celery Worker가 자식 프로세스에게 configuration object를 직렬화하지 않아도 된다는것 때문 # namespace = 'CELERY'는 모든 celery 관련한 configuration key가 'CELERY_' 로 시작해야함을 의미함 app.config_from_object('django.conf:settings', namespace = 'CELERY') # task 모듈을 모든 등록된 Django App configs에서 load 함 app.autodiscover_tasks() @app.task(bind=True) def debug_task(self): print('Request: {0!r}'.format(self.request)) | cs |
4. 프로젝트의 __init__.py를 수정한다
1 2 3 4 | from __future__ import absolute_import # Django가 시작할 때 shared_task가 이 앱을 이용할 수 있도록 app이 항상 import 되게 해준다. from .celery import app as celery_app # noqa | cs |
5. Django 프로젝트 안에 있는 app 폴더내부에 tasks.py를 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from __future__ import absolute_import, unicode_literals import random from celery.decorators import task @task(name="sum_two_numbers") def add(x, y): return x + y @task(name="multiply_two_numbers") def mul(x, y): total = x * (y * random.randint(3, 100)) return total @task(name="sum_list_numbers") def xsum(numbers): return sum(numbers) | cs |
6. migrations를 한다.
1 2 | python manage.py makemigrations python manage.py migrate | cs |
4. 실행하기
Celery 서버를 실행해보자
$ celery - worker -l info
** 오류 발생
[2018-01-30 07:56:45,445: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 111] Connection refused.
Trying again in 2.00 seconds...
--> 매우 간단한 문제였다. redis-server 가 켜져있는 상태에서 celery를 실행해야 함!
Schedule 을 작성해서 task를 실행
** crontab은 배치 작업을 위해서 특정 시간 뿐만 아니라 특정 요일과 같은 다양한 단위시간 설정을 지원한다. celery에는 이를 사용할 수 있는 모듈을 포함하고 있다. celery.schedules.crontab을 import 하여 사용할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from celery.schedules import crontab @app.task(bind=True) def debug_task(self): print('Request: {0!r}'.format(self.request)) app.conf.beat_schedule = { 'add-every-minute-contrab': { 'task': 'multiply_two_numbers', 'schedule': crontab(), # 1분마다 'args': (16, 16), }, 'add-every-5-seconds': { 'task': 'multiply_two_numbers', 'schedule': 5.0, # 5초마다 'args': (16, 16) }, 'add-every-30-seconds': { 'task': 'tasks.add', 'schedule': 30.0, # 30초마다 'args': (16, 16) }, } | cs |
tasks를 Celery Beat를 통해서 test 해본다.
1 | celery -A [프로젝트명] beat -l info | cs |
설치 및 실행해보기까지 해보았다. 이제 자기의 프로젝트에 맞게 수정해서 실행하기만 하면 된다.
- 모든 과정 -
python manage.py runserver
redis-server
-- 프로젝트가 있는 폴더에서,
celery -A [프로젝트명] worker -l info
celery -A [프로젝트명] beat -l info
출처 :
http://docs.celeryproject.org/en/master/getting-started/first-steps-with-celery.html
https://medium.com/sunhyoups-story/celery-b96eb337b9cf
http://blog.naver.com/PostView.nhn?blogId=c_ist82&logNo=220777624611
http://whatisthenext.tistory.com/127
http://sarc.io/index.php/nosql/63-redis-2-8-6
https://www.codingforentrepreneurs.com/blog/celery-redis-django/
'Django' 카테고리의 다른 글
django paginator 페이지 수 제한하기 (0) | 2018.02.20 |
---|---|
[django celery]테스크 주기 설정하기 (1) | 2018.02.02 |
python 파일 존재여부 (0) | 2018.01.29 |
csrf 및 form 구현 (0) | 2018.01.25 |
[Django] 테이블 paginator (0) | 2018.01.22 |