Python/Deployment

[배포] Python ASGI 배포 서버 종류 비교

yubi5050 2023. 6. 6. 18:14

Python ASGI 배포 서버

Python에서 웹 어플리케이션(Django, FastAPI, Flask 등)을 배포시 비동기 요청 처리를 위해, ASGI 서버를 사용하여 배포하게 되는데, Python 기반의 ASGI 서버들을 비교해보며, 종류와 특징에 대해 알아 본다.

 

주로 많이 언급되는 건 다음과 같다.

  • Uvicorn (asyncio, uvloop)
  • Daphne
  • Hypercorn
  • Starlette

 

사실 결론부터 말하자면, 사용하는 프레임워크나 기능에 따라 배포 서버에 대한 선택지가 한정적인 것으로 생각되는데

 

FastAPI로 배포를 희망

→ 공식문서에서 지원하는 Uvicorn이나 Hypercorn 을 쓰는 것이 일반적

 

Django / Flask 에 Websocket 프로토콜 처리가 필요

→ Daphne 이 적절 

 

Starlette

→ ASGI 서버 보다는, 프레임워크의 기본 기능들을 제공해주는 툴킷임.

 

Uvicorn

링크 : uvicorn 공식 문서 링크

 

정의

  • 파이썬 전용 ASGI (Asynchronous Server Gateway Interface) 서버
  • uvloop (이벤트 loop, c기반) + httptools (http 프로토콜 처리) 조합을 이용해 ASGI를 구현함

 

특징

  • 주로 FastAPI / Django Ninja 등과 함께 사용
  • uvicorn 은 단일 프로세스로 동작
  • 파이썬 언어에 내장된 asyncio의 이벤트 루프 역할을 → uvloop로 대체하여 더 빠르게 동작

 

설치 방법

# cpython 기반 dependency 설치 <- 권장
pip install uvicorn[standard] 

# event loop로 asyncio 사용
pip install uvicorn

 

배포

  • FastAPI + Gunicorn + Uvicorn (worker) 조합 으로 많이 사용

 

Q & A

Q.1 Uvicorn을 단독적으로 쓰지 않고, Gunicorn에 붙여 쓰는 이유는?

uvicorn 은 단일 프로세스로 멀티 스레딩을 통해 동작
일정 트래픽 이상 넘어 서면, 단일 프로세스에서 스레드를 통한 작업의 한계가 존재
웹 어플리케이션을 프로세스 레벨(worker)로서 관리해주는 Gunicorn에 uvicorn 각각을 worker로 붙여 배포
즉 Gunicorn이 ASGI 요청을 처리하는 Uvicorn을 Worker로 여러개로 만들어 더 많은 요청을 분산/관리해주며 보완 목적

 

Q.2 왜 비동기 방식인 Uvicorn에 한계가 존재하는가?

물론, 단일 프로세스 만으로도 높은 동시성 성능을 확보가 가능하지만, 주된 latency는 스레드의 공유 자원에 대한 병목에서 발생한다. (공유 자원을 기다리는 상황)\

 

 

Asyncio

  • Asyncio는 Python 3.5 버전 부터 내장 된 비동기 I/O 라이브러리
  • async / await 구문을 사용하여 비동기(Asynchronous) 코드 작성 가능
  • non-blocking 한 상황(API 작동시 대기 시간이 긴 경우에도 CPU가 다른 처리를 할 수 있는 상황)을 만듬

 

uvloop

  • NodeJS V8 엔진에서 사용하는 libuv(고성능 다중 플랫폼 비동기 I/O 라이브러리) 기반 
  • asyncio를 대체하기 위해 만들어졌으며, 실제 성능상 uvloop+httptools의 성능은 Go 프로그램의 성능과 비슷

 

Daphne

링크 : daphne 공식 github 링크

 

정의

  • Django Channels를 지원하기 위해 개발된  ASGI 서버
  • Django/Flask 에서 WSGI 요청과, ASGI 요청을 Channels 개념을 통해 처리

 

특징

  • HTTP, HTTP2, WS 프로토콜 처리를 지원
  • HTTP, WS 요청을 Daphne를 통해 수신 이후 Channels는 두 프로토콜을 구분하여 처리
  • 주로 채팅 시스템과 같은 websocket 이용한 개발시 많이 사용되는 것으로 보임

 

Daphne - Channels 적용 전/후 구조 비교 

  • HTTP 프로토콜은 Views로, Websocket 프로토콜은 Consumers로 둘을 분리하여 처리
  • 이러한 처리를 해주는 것 Channel Layer

좌:채널 적용 전 구조 / 우:채널 적용 후 구조

 

Hypercorn

링크 : Hypercorn 공식 github 링크

 

정의

  • Python 3.6 이상의 버전에서 사용되는 ASGI 서버

 

특징

    • 프로토콜 지원을 강조하여 HTTP/1, HTTP/2 및 HTTP/3을 지원 (HTTP/3 은 추가 라이브러리 필요)
    • (추가) sans-io (네트워크 I/O Free)를 기반 (이부분은 잘 모르겠음)
    • asyncio와 uvloop를 기반으로 하여 빠른 속도와 고성능 제공
    • Hypercorn은 작고 가벼워, 배포 및 확장이 쉬움

 

 

Starlette

링크 : starlette 공식 문서 링크

 

정의

  • Python 3.6 이상의 ASGI 프레임워크(애플리케이션)를 위한 툴킷 (ASGI 서버 보다는 툴킷이 주목표)

 

특징

  • FastAPI이 해당 Starlette 기반으로 작성되었으며, 모듈성이 매우 좋음
  • starlette은 ASGI 프레임워크끼리 공통적으로 사용 할 수 있는 기능(ex. --reload 옵션 등)의 모듈화를 목표함
  • starlette을 마운트 한 ASGI 프레임워크들 끼리는 starlette의 주요 기본 기능들을 이어 받아, 애플리케이션 구현 방식이 프레임워크 간 통일성이 생김

 

툴킷으로서의 Starlette 주요 기능

  • 가볍고, 복잡도가 낮은 HTTP Web Framework 
  • 프레임워크 인-프로세스 Background 작업
  • 시스템 start-up, shut-down 이벤트
  • WebSocket, Streaming 관련 지원
  • CORS, GZip 등 
  • 세션 및 쿠키
  • 코드 Annotation (타입 hinting)

 

참고 문헌