if __name__ == '__main__':
uvicorn.run(
app='app.main:app',
host=127.0.0.1,
port=3000,
loop='uvloop',
workers=3,
access_log=False,
)
FastAPI 를 run 하는 코드를 보다가 workers 라는게 보여서 좀 찾아봤다.
worker 는 각 서버에서 가질 수 있는 프로세스들이라고 보면 되는데,
위처럼 3개를 지정하고 서버를 띄우면 아래처럼 3개의 프로세스가 뜨는걸 볼 수 있다.
INFO: Started parent process [42123]
INFO: Started server process [42127]
INFO: Started server process [42126]
INFO: Started server process [42125]
INFO: Waiting for application startup.
INFO: Waiting for application startup.
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Application startup complete.
INFO: Application startup complete.
FastAPI 공식 문서 에서는 Uvicorn 과 같은 ASGI(Asynchronous Server Gateway Interface) server 로 서버를 띄워줘야 한다는데, 그럼 Uvicorn 으로 하면 돼지 왜 gunicorn 은 튀어나온걸까
먼저 gunicorn 은 ASGI 가 아닌 WSGI 표준을 지원하는 애플리케이션 서버다. 그리고 uvicorn 은 ASGI 프로토콜을 지원하며 cypthon 으로 구현한 uvloop 를 사용하여 비동기 서버를 구현할 수 있게 되어있다.
그럼 비동기 서버를 구동해야하는 FastAPI 는 uvicorn 을 쓰면 되겠네.
하지만 FastAPI 공식문서에서는 worker를 지정할 경우 uvicorn 보다는 gunicorn 을 사용하는게 좋다고 안내하고 있다.
Nevertheless, as of now, Uvicorn's capabilities for handling worker processes are more limited than Gunicorn's.
worker 들을 관리하는 프로세스 매니저로서의 역할을 하기에 uvicorn 이 아직 능력이 부족하다고 한다.
그럼 WSGI 기반으로 된 gunicorn 으로 어떻게 비동기 서버를 구동할 수 있을까.
Gunicorn supports working as a process manager and allowing users to tell it which specific worker process class to use. Then Gunicorn would start one or more worker processes using that class.
And Uvicorn has a Gunicorn-compatible worker class.Using that combination, Gunicorn would act as a process manager, listening on the port and the IP. And it would transmit the communication to the worker processes running the Uvicorn class.
And then the Gunicorn-compatible Uvicorn worker class would be in charge of converting the data sent by Gunicorn to the ASGI standard for FastAPI to use it.
Gunicorn 은 특정 worker 프로세스 클래스를 사용해서 프로세스 매니저를 사용할 수 있는 기능을 지원한다. 그리고 Uvicorn 은 Gunicorn 에 호환가능한 worker 클래스를 가지고 있다.
이 조합을 이용해서 Gunicorn 으로 Univorn 의 Gunicorn 호환 가능 worker 클래스를 가져다가 쓰는 개념으로 보인다. 호환 클래스는 Gunicorn에서 보낸 데이터를 FastAPI에서 사용할 수 있도록 ASGI 표준으로 변환하는 작업을 담당한다고 한다.
클래스는 ASGI 프로토콜인 Uvicorn worker 를 쓰고 그 관리는 Gunicorn 으로 한다. 그럼 무조건 Gunicorn 으로 사용하면 되는건가?
그건 또 아니다. 데브옵스와 여러가지를 고려해봐야할거 같긴한데.
일단 쿠버네티스를 통해 로드밸런싱으로 worker 를 하나만 가진 서버들에 부하를 분산할 수도 있고, 아니면 worker 를 적게 활용해도 되어 uvicorn 의 능력이 부족함에도 큰 문제가 없이 사용될 수도 있다.
아직 여기까진 지식이 미치지 않아 실제로 서버를 올리는 시점이 될 때 여러가지 테스트를 통해 취사선택을 해봐야겠다.
What is the difference between Uvicorn and Gunicorn+Uvicorn? - stackoverflow
Server Workers - Gunicorn with Uvicorn