일반적인 파이썬 코드에서는 동기 함수는 순서대로 작동하고, 비동기 함수는 병렬적으로 작동합니다. 그럼 FastAPI 내의 동기 함수만을 이용한 엔드포인트에 다수의 HTTP 요청을 보내면 동기 함수를 실행하느라 서버가 요청을 받지 못하는 상황이 될 것 같다는 의문이 들었습니다. 의문을 해결하기 위해 내부적으로 FastAPI가 어떤 식으로 동작하는지 알아보겠습니다.
우선 다음과 같이 작성된 동기 함수로 작성된 엔드포인트에 `curl`을 이용하여 두 번의 HTTP 요청을 보내보겠습니다.
@app.get("/sync")
def sync():
print("Hello")
time.sleep(2)
print("Bye")
# In run_sync.txt
url = "http://127.0.0.1:8000/sync"
url = "http://127.0.0.1:8000/sync"
# Run parallel requests using curl
curl --parallel --parallel-immediate --parallel-max 2 --config run_sync.txt
파이썬에서 동기 함수가 동작하는 방식을 생각한다면 다음과 같은 출력을 얻을 것 같습니다.
Hello
Bye
Hello
Bye
하지만 실제로 2번의 요청을 보내면 마치 비동기 함수가 동작하는 방식과 같이 출력이 이루어집니다. 파이썬에서 동기 함수는 호출된 함수가 종료될 때까지 제어권을 호출자에게 넘겨주지 않아야 하는데 왜 저런 결과가 나왔을까요?
Hello
Hello
Bye
Bye
답은 공식 문서에 있습니다!
When you declare a path operation function with normal def instead of async def, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
FastAPI와 같은 웹 프레임워크에서 동기 함수를 순서대로 처리하게되면 하나의 작업이 진행되는 동안 서버가 Blocking되는 현상이 발생할 것입니다. 이러한 현상을 막기 위해 FastAPI는 내부적으로 동기 함수에 대한 요청을 별도의 스레드풀에서 작업한다고 합니다. 그렇기 때문에 파이썬에서 멀티스레드를 이용할 때와 동일한 결과를 얻게 되는 것입니다.
그럼 실제로 동기 함수가 메인 스레드와 다른 스레드에서 작동하는지, 각각의 요청이 서로 다른 스레드에서 작동하는지 확인해보겠습니다.
import threading
print(f"Main thread id: {threading.get_ident()}") # Print main thread id
@app.get("/sync")
def sync():
tid = threading.get_ident()
print(f"Hello {tid}")
time.sleep(2)
print(f"Bye {tid}")
Main thread id: 8675603968
INFO: Started server process [13799]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Hello 13082910720
Hello 13099700224
Bye 13082910720
Bye 13099700224
INFO: 127.0.0.1:51565 - "GET /sync HTTP/1.1" 200 OK
INFO: 127.0.0.1:51566 - "GET /sync HTTP/1.1" 200 OK
위 결과를 통해
1. 동기 함수는 메인 스레드(8675603968)가 아닌 다른 스레드에서 동작
2. 두 개의 요청이 서로 다른 스레드(13082910720와 13099700224)에서 동작
하는 것을 확인할 수 있었습니다.
잘못된 내용, 오타, 부정확한 문장 등 어떤 피드백이든 환영합니다. 감사합니다.
References
'CS > Python' 카테고리의 다른 글
[FastAPI]FastAPI의 비동기 함수 동작 방식 (0) | 2023.03.24 |
---|---|
[Python] Class에서 특정 문자열로 시작하는 Method 찾기 (0) | 2022.05.25 |
[Python] 주어진 문자열이 알파벳/숫자로만 구성되었는지 확인해보기 (0) | 2022.04.20 |