개요
쿠버네티스 백엔드 pod가 livenessprobe가 실패하여 pod재부팅이 된 상황을 직면했습니다. 자세히 살펴보니 비동기 로직이 올바르게 구현되어 있지 않아 probe가 실패했습니다.
이 글은 비동기 로직을 수정하기 위해 공부한 내용을 정리했습니다. 영상으로도 만나볼 수 있습니다.
영상: https://youtu.be/hS-6fJJpAgk
fastapi 비동기 로직
먼저 fastapi가 어떻게 비동기를 처리하는지 살펴봤습니다. fastapi는 ASGI Framework로 구현된 웹 애플리케이션입니다. 그리고 fastapi를 실행하는 uvicorn은 ASGI Framework를 실행하는 ASGI Server역할을 수행합니다. 이 구조는 WAS<->spring boot와 거의 비슷하다고 느꼈습니다.
구조의 핵심은 uvicorn의 존재입니다. uvicorn의 공식문서를 살펴보면 uvicorn가 실행하는 uvloop가 비동기 로직을 처리한다고 설명합니다. 그러므로 fastapi의 비동기 로직은 파이썬이 비동기를 처리하는게 아니라 uvloop가 대신 처리합니다.
비동기 지연의 문제 추측
uvloop의 정확한 로직은 모르겠지만... nodejs의 libuv처럼 동작한다면 비동기 큐가 있을 거라 생각했습니다. fastapi가 요청받은 비동기 이벤트를 큐를 통해 uvloop로 전달합니다. 그리고 uvloop는 일정주기마다 반복되어 큐에 있는 비동기 이벤트를 처리하는 것으로 해석했습니다. 그러므로 이벤트 한개에 의도하지 않은 지연이 생기면 뒤에 대기하고 있는 비동기 이벤트도 같이 지연될 거라 생각했습니다.
실험
비동기 endpoint에 sleep함수를 추가하여 비동기 로직을 강제로 지연시켰습니다. 그리고 endpoint를 동시에 5번 요청했습니다.
from fastapi import FastAPI
import time
app = FastAPI()
@app.get("/hello")
async def hello():
time.sleep(3)
return {"hello": "world"}
클라이언트는 쉘스크립트와 curl을 이용했습니다.
#!/bin/bash
set -e
function run() {
# change your IP
endpoint=$1
for i in $(seq 5);do
echo "=== count: $i endpoint: $endpoint ==="
curl -s -o /dev/null $endpoint &
done
wait
}
time run $1
예상한대로 비동기 한 구간에서 지연이 생기면 다른 비동기 구간도 그만큼 지연이 생겼습니다. 그래서 총 5번 요청하면 약 15초 지나야 모든 응답이 도착했습니다.
자세한 실험과정은 제 유투브 영상을 참고해주시면 감사하겠습니다.
영상: https://youtu.be/hS-6fJJpAgk?t=337
'회고모음' 카테고리의 다른 글
python 자식 쓰레드에서 signal 처리 오류 (0) | 2023.01.15 |
---|---|
uuid를 잘못 설정하여 오류를 만나다. (0) | 2023.01.09 |
Elasticsearch 지연 현상 (3) | 2023.01.05 |
2022년 회고 (8) | 2023.01.02 |
nginx ingress 존재 때문에 보안 취약점 받은 nginx pod (0) | 2022.12.27 |