2019. 11. 23. 01:01 ㆍ개발 이야기/python
#1 monit 편 이후에 너무 늦어졌네여 ㅜㅜ
요즘 결혼준비와 일 그리고 대학원까지 준비하면서 너무 바쁘다 보니
블로그를 쓸 시간이 너무 부족한 요즘입니다...
자 그럼!!
음성인식 B2C 서버를 구축하기 위해서 백엔드를 구축할 때!
어쩌면 가장 중요할 수도 있는 부분인데요
음성인식은 디코딩 시간이 상당히 길기 때문에
절대적으로 비동기로 진행을 해야 합니다!
동기/비동기란 무엇이냐?
이런 것입니다. 추가적으로 설명을 하자면!
동기는 job이 끝날 때까지 기다리구요!
비동기는 jobs이 끌 날 때까지 기다리지 않습니다!
그러면 여러 리퀘스트를 받게 되면?
동기는 트랜잭션을 하나씩 처리를 하고 하나의 트랜잭션이 끝나지 않으면
다른 요청은 계속~ 기다리고 있겠죠!
시간이 오래 걸리는 트랜잭션을 비동기 처리를 하면
트랜잭션을 백그라운드로 던지고 자원을 다른 트랜잭션에 사용할 수 있게 됩니다!
참 쉽죠!
그러기 위해서는 분산작업을 해주는 것이 필요한데
Celery라는 것이 있습니다!
이 Celery는 큐를 기반으로 하는 분산 작업 대기열인데요 !
Celery is an asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation, but supports scheduling as well.
The execution units, called tasks, are executed concurrently on a single or more worker servers using multiprocessing, Eventlet, or gevent. Tasks can execute asynchronously (in the background) or synchronously (wait until ready).
Celery는 분산 메시지 전달을 기반으로 하는 비동기 작업 대기열 / 작업 대기열입니다. 실시간 작업에 중점을 두지 만 예약도 지원합니다.
태스크라고 하는 실행 단위는 멀티 프로세싱, Eventlet 또는 gevent를 사용하여 하나 이상의 작업자 서버에서 동시에 실행됩니다. 작업은 비동기 적으로 (백그라운드에서) 또는 동 기적으로 (준비될 때까지 대기) 실행할 수 있습니다.
큐가 뭔지는 다들 알고 계시죠!?
FIFO(First In First Out) 구조로 먼저 들어온 jobs을 순서대로 처리해주는 자료구조입니다
이 큐와 Celery를 어떻게 이용해서 비동기 작업을 할 수 있을까요??
자! 이 부분에서 새로운 개념이 몇 가지 등장합니다!
Producer : 메시지를 보내는 Application(WSGI, WAS)
Queue : 메시지를 저장하는 큐
Consumer : 메시지를 받아 동작
Message Broker : 메세지 중계인(여기서는 Queue와 동일한 개념)
이렇게 개념만 보면 조금 어렵게 생각이 될 수 있지만!
사실은 별것이 없습니다.
Producer는 말 그대로 비동기 처리를 할 요청을 Message Queue 즉, Message Broker에게
전달을 하고 이 메시지를 차례대로 가져와 비동기 작업을 수행하는 것이 Consumer
Celery(Worker) 입니다!
그림으로 보여드리겠습니다.
WSGI를 통해 Message Queue로 비동기 처리해야 하는 요청이 쌓이면
Worker인 Celery는 차례로 메시지를 가져다가 처리하는 방식으로 워크 플로우가 진행됩니다.
간단한 설정과 어떻게 구현하는지를 알아보도록 하겠습니다.
먼저 RabbitMQ 설치 후 간략한 설정을 해보겠습니다!
# rabbitmq 설치!
apt-get install rabbitmq-server
# rabbitmq 실행
/etc/init.d/rabbitmq-server start
# rabbitmq의 웹 관리자 페이지를 사용하기 위한 명령어(비추)
rabbitmq-plugins enable rabbitmq_management
# guest 계정의 비밀번호 설정
rabbitmqctl change_password guest '사용하고싶은 비밀번호'
# test라는 virtual host 생성
rabbitmqctl add_vhost test
# test virtual host의 guest에게 모든권한 부여
rabbitmqctl set_permissions -p test guest ".*" ".*" ".*"
* 퍼미션 부여 방법
set_permissions [-p vhostpath] {username} {conf} {write} {read}
conf : 사용자에게 구성 권한이 부여 된 리소스 이름과 일치하는 정규식입니다.
write : 사용자에게 쓰기 권한이 부여 된 리소스 이름과 일치하는 정규식입니다.
read : 사용자에게 읽기 권한이 부여 된 리소스 이름과 일치하는 정규식입니다.
이렇게만 설정해주면 rabbitMQ 설정은 끝!
다음은 Celery 설치 및 간략한 설정과 소스코드를 보겠습니다.
pip으로 설치를 해줍니다
pip install celery
Celeryd 샐러리 데몬을 설치해줍니다!
apt-get install celeryd
그렇게 되면
/etc/init.d/celeryd,
/etc/default/celeryd
이게 생성이 됩니다!
먼저, /etc/init.d/celeryd를 살펴보겠습니다.
celeryd 데몬을 실행하는 파일로 vi로 열어보면
이렇게 로그가 어디 쌓이는지 설정파일(CELERY_DEFAULTS)을 어디에다 설정하는지를 볼 수 있으며
아래와 같은 명령어를 사용할 수 있습니다
/etc/init.d/celeryd start # 샐러리 데몬 실행
/etc/init.d/celeryd stop # 샐러리 데몬 정지
/etc/init.d/celeryd restart # 샐러리 데몬 재실행
/etc/default/celeryd 는 무엇이냐!
바로 설정 파일입니다!
초기 그대로의 모습입니다
CELERYD_CHDIR은 프로젝트 소스코드가 있는 곳
CELERYD_OPTS는 시간 설정과 몇 개의 샐러리를 띄울지 결정합니다
CELERY_USER, CELERY_GROUP은 말 안 해도 아시겠지만
어떤 권한으로 데몬을 실행할지 기입합니다.
celery 권한으로 실행한다는 뜻입니다.
저는 --concurrency를 4로 설정했기 때문에
이렇게 4개의 프로세스가 띄어져 있는 것을 볼 수 있습니다.
저는 아래와 같이 바꿔서 사용하고 있습니다.
CELERY_APP 은 Celery를 생성하는 부분!
저는 main의 celery 변수에 만들어 주었고 아래와 같습니다.
def make_celery(app):
celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
# config.py
CELERY = {
'CELERY_BROKER_URL' : 'amqp://guest:아까 넣고싶은 비밀번호@localhost/test'
}
자 그러고 나서!
celery에게 주고 싶은 함수에 위와 같이 데코레이터를 붙여줍니다!
사용하고 싶은 위치에 아래와 같이 사용하면 되는데요!!
위와 같이 Celery를 호출할 때는 몇 가지 방법이 있습니다.
T.delay(arg, kwarg=value)
별표 인수 바로 가기 .apply_async입니다. ( 호출 )..delay(*args, **kwargs).apply_async(args, kwargs)
T.apply_async((arg,), {'kwarg': value})
T.apply_async(countdown=10)
지금부터 10 초 안에 실행됩니다.
T.apply_async(eta=now + timedelta(seconds=10))
지금부터 10 초 안에 실행됩니다. eta
T.apply_async(countdown=60, expires=120)
지금부터 1 분 안에 실행되지만 2 분 후에 만료됩니다.
T.apply_async(expires=now + timedelta(days=2))
로 설정하여 2 일 후에 만료됩니다 datetime.
http://docs.celeryproject.org/en/latest/userguide/calling.html
이렇게 타이머를 설정할 수도 있고 expire 시간을 설정할 수도 있습니다!
여기까지 비동기 작업을 할 수 있는 Celery와 rabbitMQ를 알아보았는데요!
이렇게 하면 비동기 B2C 서비스를 성공적으로 마무리할 수 있는가!!?
물론 작은 규모의 서비스면 충분히 마무리지을 수 있지만
리소스 소모가 엄청나게 큰 음성인식 서비스를 하기에는 아직도 무리가 있는 것을 알 수 있습니다!
그래서 다음에는 AWS에서 Load Balancer와 Autoscale을 통해
사용자의 사용량에 따라 어떻게 이겨낼 수 있는지 적어보도록 하겠습니다!@!
읽어주셔서 감사합니다(--)(__)
'개발 이야기 > python' 카테고리의 다른 글
# PYTHON PANDAS 특정 행 이하 제거 (1) | 2021.11.11 |
---|---|
[회귀분석] COVID-19 확산 지표와 교통 통계량 데이터를 이용한 회귀분석 과정 (0) | 2021.07.04 |
# anaconda 64bit 설치 후 32bit python 사용하기 (0) | 2020.09.02 |
보안뉴스(boannews.com) 크롤러 텔레그램 연동 (0) | 2019.09.05 |
python 아나콘다 사용 방법(pycharm ssh interpreter) (0) | 2019.08.06 |