[백엔드 기초] 6. Web server(Nginx, Gunicorn, Dramatiq)
Web/Backend

[백엔드 기초] 6. Web server(Nginx, Gunicorn, Dramatiq)

 

Web server 개요

 

1. 클라이언트

웹서버(Nginx)로 HTTP 요청

2. 웹서버(Nginx)

웹 서버. 클라이언트로부터의 HTTP요청을 받아 정적인 페이지/파일을 돌려줌. (동적인 부분은 uWSGI가 담당) 가벼움과 높은 성능이 목표. 웹 서버, 리버스 프록시 및 메일 프록시 기능을 가짐.

3. Unix Socket

웹서버(Nginx) - 웹어플리케이션서버(uWSGI) 사이의 통신을 매개 HTTP 요청을 사용할 수도 있지만 서버 안쪽에서의 통신이기 때문에 socket 방식이 overhead가 적어서 더 효율이 좋음

4. 웹어플리케이션서버(uWSGI)

웹 서버(Nginx)와 웹 애플리케이션(Django)간의 연결을 중계 (Nginx에서 받은 요청을 Django에서 처리하기 위한 중계인 역할) Nginx는 Python을 모르기 때문에 uWSGI는 HTTP 요청을 python으로, Django로 부터 받은 응답을 Nginx가 알 수 있도록 변환해줌.

5. Django

웹 애플리케이션. 웹 요청에 대해 동적데이터를 돌려줌.

* WSGI

Web Server Gateway Interface파이썬에서 웹 서버와 웹 애플리케이션간의 동작을 중계해주는 인터페이스 표준 웹클라이언트의 HTTP 프로토콜 요청을 Python Call로 변환하기 위한 매핑관계로 WSGI를 표준으로 사용. uWSGI는 WSGI 표준의 구현

 

Django 프로젝트 생성 후 서버 실행시

./manage.py runserver (= python manage.py runserver)

 

하지만, 이것은 debug용으로 local에서만 사용해야 하고 실제 production 환경에서는 자제해야 함

Django 공식 문서에서도 production setting에서 사용하지 말라고 주의를 주고 있음

(보안 및 퍼포먼스 이슈 있을 수 있음)

그리고 두번째 줄에 보면 Django는 Web server가 아니라고 말함.

"우리는 웹 프레임워크를 만들지 웹 서버를 만드는 건 아니다. 그래서 실서버 환경에서 다룰 수 있는 건 Django의 영역 밖이다."

Django는 Web Server 가 아니라 Web Framework!

 

WSGI, uWSGI, uwsgi

일반적으로 웹 서버( Apache, Nginx )는 톰캣, PHP, Django, Node.js 등의 앞단에 배치되어 프록시, 보안, 정적 파일 제공 등의 역할을 함. 그런데 웹 서버는 PHP, Python, JavaScript 등의 언어를 해석할 능력이 없기 때문에 프로그래밍 언어를 해석할 수 있는 인터페이스, 즉 CGI가 필요함.

 

WSGI는 python 애플리케이션과 웹 서버가 통신하기 위해 정의된 표준 인터페이스. CGI와 WSGI는 웹 요청을 처리할 수 있는 표준 인터페이스 프로그램이라는 점에서 같지만, CGI는 WSGI보다 low level에 있음.

 

uWSGI는 애플리케이션을 처리 할 수 있는 애플리케이션 서버 컨테이너. WSGI 스펙에 정의 된 방법을 사용하여 python 애플리케이션과 통신하고, 프로토콜( 기본 프로토콜 : uwsgi )을 통해 다른 웹 서버와 통신함. 즉, 기존의 웹 서버에 대한 요청을 애플리케이션이 처리할 수 있도록 변환하는 부분.

 

uwsgi는 uWSGI가 웹 서버와 통신하기 위해 구현된 프로토콜. uWSGI를 통해 Nginx와 Django를 연동하고자 할 떄 Django에서 프로젝트를 생성하면 WSGI 프로세스를 사용할 수 있도록 정의된 wsgi.py 파일을 제공해주기 때문에 쉽게 연동이 가능함.

 

wsgi 분리

 

uwsgi 명령을 통해서 직접 웹어플리케이션 서버를 실행할때 사용할 설정 파일을 실행환경별로 분리(실행 환경별로 필요한 프로젝트 설정이 다르기 때문)

  • base.py (공통)
  • debug.py (개발용)
  • deploy.py (배포용)

 

project_folder/
    .config_secret/
        settings_common.json
        settings_debug.json
        settings_deploy.json
    django_app/
        config/
            settings/
              __init__.py
              base.py
              debug.py
              deploy.py
            wsgi
              __init__.py
              debug.py
              deploy.py
            __init__py
            urls.py
        manage.py
    ..

 

wsgi/debug.py 예시

import osfrom django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.debug")

application = get_wsgi_application()

wsgi/deploy.py 예시

import osfrom django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.deploy")

application = get_wsgi_application()

 

runserver

  • 장고는 DJANGO_SETTINGS_MODULE 환경변수를 통해서 참고할 settings 파일의 경로를 확인
  • 환경변수가 설정되지 않으면 wsgi.py 의 설정값을 사용
  • 혹은 python3 manage.py runserver 시에 -settings 옵션을 통해서 지정 가능
# local development
python3 manage.py runserver --settings=config.settings.debug

# 환경변수 설정예시
export DJANGO_SETTINGS_MODULE=config.settings.debug
echo $DJANGO_SETTINGS_MODULE

 

wsgi.py

"""
WSGI config for qduoj project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "oj.settings")

application = get_wsgi_application()

 

setting.py

production_env = get_env("OJ_ENV", "dev") == "production"
if production_env:
    from .production_settings import *
else:
    from .dev_settings import *
.
.
.
WSGI_APPLICATION = 'oj.wsgi.application'

 

Gunicorn

(Green UNICORN)

gunicorn은 Python WSGI HTTP Servergunicorn은 상대적으로 빠르고 가볍고 사용이 쉬움.

  • 간단한 Python configuration
  • Multiple worker configurations
  • 확장성(extensibility)을 위한 다양한 Server hook들
  • python2.6+ 그리고 python3.2+ 과 호환 가능

 

Django에서는 wsgi.py에서 application = get_wsgi_application() 를 통해 wsgi handler를 가져옴.

wsgi handler에서는 middleware등 을 처리하고, WSGI server에서는 설정을 읽어 application의 경로를 가져옴.

Django 기본 명령어인 runserver 명령은 WSGI_APPLICATION 설정에서 경로를 가져옴.

 

 

 

Dramatiq

 

Dramatiq: 백그라운드 task processing을 도와주는 python 라이브러리

  1. 설치
    $ pip install django-dramatiq-pg
  1. settings.pyINSTALLED_APPS 리스트에 추가
    INSTALLED_APPS = [
        ...
        'django_dramatiq_pg',
    ]
  1. Registry/tasks 생성
    from django_dramatiq_pg.registry import Registry
    
    tasks = Registry()
    
    
    @tasks.actordef mytask():
        ...
  1. 설정
    DRAMATIQ_BROKER = {
        "OPTIONS": {
            "url": "postgres:///mydb",
        },
        "MIDDLEWARE": [
            "dramatiq.middleware.TimeLimit",
            "dramatiq.middleware.Callbacks",
            "dramatiq.middleware.Retries",
        ],
    }
    DRAMATIQ_REGISTRY = 'myapp.registry.tasks'
  1. worker process 시작
    $ dramatiq django_dramatiq_pg.worker


728x90

'Web > Backend' 카테고리의 다른 글

Tools for load test  (0) 2021.06.10
[백엔드 기초] 7. DB Parallelization  (0) 2021.06.01
[백엔드 기초] 5. Docker  (0) 2021.06.01
[백엔드 기초] 4. Database, PostgreSQL  (0) 2021.06.01
[백엔드 기초] 3. Django REST Framework  (0) 2021.06.01