728x90
반응형

개요

FastAPI는 비동기 프레임워크로 ASGI 서버를 지원하는 Uvicorn 과 함께 기동되어 사용된다. 다른 Flask, Django와 비교하여 성능이 2배정도 빠르다고 알려져있다. 하지만 성능이 빠르다고한들 개발자가 사용방법을 모르고 개발한다면 제대로 된 성능을 끌어올리기에는 어려움이 있을 수 있다. 우리는 정말 제대로 알고 사용하고 있는것인가?

 

이번 포스팅에서는 Uvicorn이 반드시 Guicorn과 결합이 필요한지에 대하여 알아보고자한다.

 

배경지식

Gunicorn이란 무엇인가?

Gunicorn 은 WSGI 프로토콜을 사용하여 웹 애플리케이션과 상호 작용하는 서버이자 프로세스 관리자이다. Flask 또는 Django 와 같은 WSGI  동기식 웹 프레임워크로 작성된 애플리케이션을 제공한다. Gunicorn은 여러 인스턴스 실행을 관리하여 상태를 체크하며 요청에 대하여 해당 인스턴스에 분산시키고 웹 서버와 통신한다. Gunicorn은 매우 빠르고 이를 최적화하기 위해 많은 노력을 기울였다. 

Uvicorn이란 무엇인가?

Uvicorn 은 ASGI 서버를 지원하는 애플리케이션 서버이다.  또한 여러 작업자 프로세스를 시작하고 실행하는 옵션도 있지만 Gunicorn보다 더 제한적이다.

 

Python의 Thread의 한계

GIL(Global Interpreter Lock)은 CPython 인터프리터(파이썬의 표준 구현체)에서 사용되는 개념이다. GIL은 파이썬 스레드에서 한 번에 하나의 스레드만 Python 바이트코드를 실행하도록 제한하는 메커니즘이다. GIL은 파이썬이 C 언어로 작성된 확장 모듈을 사용할 때 스레드 안전성을 보장하기 위해 도입되었다.

 

 

각설하고 예를 들어보자. 코어가 2개 달린 CPU있다고 가정하자. 웹 프레임워크 안에서 멀티 스레드로 여러개 데몬을 띄우던 상관없이 CPU 코어 2개가 있는데도 불구하고 GIL 락으로 인하여 1개밖에 사용하지 못한다는 제한점이 있다. 그렇기때문에 CPU를 여러개 점유하기 위해서는 여러 프로세스를 사용해야한다.

 

Uvicorn + Gunicorn 무조건 사용해야하는가?

정답은 아니다. 서버 시스템 구조에 따라서 다르게 사용해야한다.

베어메탈 서버(Bare Metal Server) 경우

Uvicorn은 단일 프로세스로 비동기 요청에 효과적이지만 단일 프로세스 한계로 처리량을 더 늘리기 위해서는 멀티 프로세스를 활용해야 한다. Gunicorn은 프로세스 관리자로 WSGI 웹 프레임워크를 처리하는 데 뛰어나다. 이를 활용하여 Uvicorn이 Gunicorn의 워커 프로세스로서 동작하게 할 수 있다.

 

Uvicorn은 자체적으로 Gunicorn을 지원하는 Worker Class(uvicorn.workers.UvicornWorker)를 포함하여 Gunicorn 실행시 이 클래스 경로를 Gunicorn 실행시 -k 파라미터로 전달하여 동작하게 할 수 있다.

 

실행 예)

gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app

 

이로 인하여 Uvicorn + Gunicorn의 결합으로 인하여 양쪽의 장점을 모두 활용하여 높은 성능과 안정성을 갖춘 웹 서비스를 구축할 수 있다.

 

분산 시스템 (Kubernetes , Docker Swarm) 경우

분산 컨테이너 시스템 Kubernetes , Docker Swarm 등과 같이 클러스터가 있는 경우 과  프로세스 관리자(gunicorn)를 사용하는 대신 클러스터 수준에서 복제를 처리하는것이 좋다.  Kubernetes은 Service 리소스를 사용하여 여러 개의 Pod(컨테이너)에 대한 로드 밸런싱을 지원하며 컨테이너 복제를 처리하는 통합된 방법이 있다. 모두 클러스터 수준에서 수행된다. 이러한 경우 Uvicorn 작업자와 함께 Gunicorn과 같은 프로세스를 실행하는 대신 Docker 이미지를 빌드하고 단일 Uvicorn 프로세스를 실행하는 것이 좋은 방법이다.

 

결론

  • 베어메탈 서버(Bare Metal Server)일 경우는 Uvicorn + Gunicorn을 같이 활용하자
  • 분산 시스템 (Kubernetes, Docker Swarm)일 경우는 Uvicorn만 사용하여 클러스터 수준에서 수행하자
728x90
반응형