-
Gunicorn 동작 과정 알아보기파이썬/Django 2021. 10. 10. 14:15
파이썬 웹 애플리케이션과 웹 서버 사이에 위치하는 Gunicorn 이라는 WSGI가 어떻게 동작하는지 알아본다.
WSGI?
Web Server Gateway Interface의 약자로 파이썬의 WAS이다.어떻게 Gunicorn이 내 장고 애플리케이션을 동작시키는지?
- WSGI서버와 이 WSGI로 동작하기 위한 애플리케이션 사이에 지켜지는 hook들이 있는데 이 hook을 가지고 wsgi서버가 애플리케이션을 실행시킴
import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_defaults.settings") application = get_wsgi_application()
장고에서는 wsgi.py에 있는 application callable 변수(hook)를 제공함으로써 wsgi서버가 장고를 실행시킬 수 있다!
Gunicorn 동작 과정은?
1. 우선 Gunicorn은 이 함수를 통해 실행된다.
이 내부를 들여다 보면
Arbiter
라는 애플리케이션의 최상위 클래스에 도달해서 실질적으로 워커 프로세스를 생성하고 삭제하는 작업들을 한다.- 메인 쓰레드는 while문을 돌면서 매니징 하고 워커들을
self.manage_workers()
라는 메서드 내에서 생성된다.
2. 워커를 생성한다.
- pre-fork 모델??
- Gunicorn은 워커 모델과 다르게 pre-fork모델이다.
- pre-fork 모델이란 마스터 쓰레드가 각각 요청들을 핸들링하기 위해 '요청이 들어오기 전에' 자식 프로세스를 만든다는 의미이다.
os.fork()
콜을 통해 프로세스가 실질적으로 fork된다.worker.init_process()
메서드를 실행함으로써 이제 요청을 받을 수 있다.
3. 각각 worker가 WSGI 서버를 시작한다.
여기서 WSGI서버란 Gunicorn을 뜻하는 것이 아니라 gevent워커들이 웹애플리케이션을 실행시켜 요청 응답을 핸들링 하기위한 서버 instance이다.
self.server_class
는gevent.pywsgi
의WSGIServer
- 실제로 처리하는 건
WSGIHandler
4. WSGIHandler가 웹서버 요청을 받아 장고에 전달 후 결과를 받아 웹 서버에 응답한다.
크게 보면 self.handle_one_request() 을 메서드를 실행해서 장고 애플리케이션에 요청를 전달한 후 장고 애플리케이션으로부터 response를 받아 self.socket 을 통해 해당 응답을 웹서버에 전달한다.
handle 로직을 순서대로 보면
a.
self.handle_one_request()
에서 웹서버로 부터 요청을 읽어들인다.b.
self.handle_one_response()
- 장고 애플리케이션을 실행시켜
request
를 전달 후 응답을 받는다.
c.
self.run_application
self.application
: 이게 바로 django에서 제공 해준 application(hook)이다- self.process_result() 를 통해 장고로 부터 받은 응답을 웹서버에게 소켓을 통해 전달한다!
총 정리
- WSGIApplication(Gunicorn) 시작한다.
- 워커(자식 프로세스)를 생성한다. 메인 쓰레드는 while문을 돌면서 워커들을 관리
- 각각 워커가 WSGIServer를 시작한다.
- WSGIServer란 gevent워커들이 웹애플리케이션을 실행시켜 요청 응답을 핸들링 하기위한 서버
- WSGIServer의 핸들러인 WSGIHandler가 웹서버 요청을 받아 장고에 전달 후 결과를 받아 웹 서버에 응답한다.
데이터의 흐름
- WebServer --(socket)--> WSGIHandler --(hook call)--> Django --(hook return)--> WSGIHandler --(socket)--> WebServer
참고
'파이썬 > Django' 카테고리의 다른 글
Docker + Django에 Gitlab-CI(Pytest) 붙이기 (0) 2021.10.24 [Django] Django의 동작 원리와 과정 파헤치기 (1) 2021.10.20 [Django] GenericForeignKey (0) 2021.05.23 [Django] RestFramework 페이지네이션 종류 (0) 2021.05.05 [Django] Elastic Beanstalk에 AWS Elasticache Redis 사용하기 (0) 2021.04.05