django의 Uvicorn 사용법 정리 - 명령어 실행, 설정 파일로 실행
공식 사이트 : https://www.uvicorn.org/
gunicorn settings 문서 : https://docs.gunicorn.org/en/latest/settings.html#config-file
- uvicorn은 다중 worker를 만들고 관리하는데 아직 안정적이지 못하다. 그래서 gunicorn을 사용하여 worker를 관리하고 uvicorn으로 비동기 통신을 하는 방법을 많이 사용한다.
- 자세한 사항은 다음 blog의 글을 보자
- https://medium.com/@ashins1997/django-channels-nginx-and-uvicorn-473423315b75
1. 명령어로 실행하는 방법
gunicorn -k uvicorn.workers.UvicornWorker --access-logfile ./gunicorn-access.log main:app --bind 0.0.0.0:8000 --workers 2 --daemon
- k uvicorn.workers.UvicornWorker: Uvicorn worker 클래스 정의
- access-logfile ./gunicorn-access.log: Gunicorn 로그 파일 정의
- main:app: main.py의 app 정의
- workers 2: worker process의 수 정의, 통상 CPU 코어 개수 * 2로 설정
- daemon: 데몬 설정
- bind 0.0.0.0:8000: 8000 포트에 서버를 연결
* 주의 사항으로, gunicorn과 uvicorn을 함께 설치해줘야 한다.
2. 설정 파일로 실행
- gunicorn.conf.py
import multiprocessing
from datetime import datetime
import os
# 바인딩 주소 및 포트
bind = "0.0.0.0:8000"
# Gunicorn 워커 설정
# workers = multiprocessing.cpu_count() * 2 + 1
workers = 4
worker_class = "uvicorn.workers.UvicornWorker" # Uvicorn 워커 클래스 사용
# worker_connections = 1000 # 최대 동시 연결 수
# 프로세스 관리 설정
# pidfile = '/tmp/gunicorn.pid' # 백그라운드에서 pid 파일 생성 (데몬 모드와 함께 사용)
daemon = False # 데몬 모드 설정 (True일 경우 백그라운드 실행)
# ASGI 애플리케이션 경로 설정
wsgi_app = "config.asgi:application"
# 타임아웃 설정
timeout = 30 # 타임아웃 설정 (초)
keepalive = 2 # Keepalive 타임아웃 (초)
graceful_timeout = 30 # Graceful 타임아웃 설정 (초)
# 프로세스 리소스 관리
max_requests = 1000 # 워커당 처리할 최대 요청 수
max_requests_jitter = 50 # 최대 요청 흩어짐 설정
# 프로세스 재시작 옵션
preload_app = False # 앱 로딩 지연 설정
reload = True
# 로깅 설정
loglevel = "info" # 로그 레벨
accesslog = f"/log/uvicorn/access_{datetime.now().strftime('%Y-%m-%d_%H')}.log"
errorlog = f"/log/uvicorn/error_{datetime.now().strftime('%Y-%m-%d_%H')}.log"
# access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' # 로그 형식 설정 (액세스 로그의 형식을 지정)
# statsd_host = 'localhost:8125' # 성능 분석을 위해 구니콘의 내부 통계를 수집할 경로 설정
- timeout
- 각 worker 프로세스는 default로 30초의 timeout을 가지는데 위 예시에서는 30초로 설정
- 실행이 오래걸리는 작업이 있다면 timeout을 더 늘리면 되며, timeout 시간이 지나면 worker프로세스는 자동으로 종료되고 재실행된다.
- max_requests
- 메모리 누수를 방지하기 위해 하나의 worker가 받는 최대 요청
- 만약 설정하지 않으면 worker가 죽을 때만 재실행된다.
- max_requests_jitter
- 모든 woker가 동시에 재실행되는 것을 방지하기 위한 설정
- 예시에서는 50으로 설정되었는데 이 경우 950에서 1050 사이의 요청을 처리한 후 재시작한다.
- 실행 방법
gunicorn -c gunicorn.conf.py
- uvicorn의 확인 방법
- docker 컨테이너 내부 혹은 root 위치에서 uvicorn --version을 했을 때, run으로 시작하는 메시지가 출력하면 현재 uvicorn이 동작하고 있는 것이다.
- reference :
https://yscho03.tistory.com/328
https://rgbitcode.com/blog/senspond/58
https://docs.djangoproject.com/ko/5.0/howto/deployment/asgi/uvicorn/
https://velog.io/@so-eun/Python-gunicorn-uvicornwsgi-asgi
https://medium.com/@ashins1997/django-channels-nginx-and-uvicorn-473423315b75