FastAPI에서 OpenAI API 호출 한도 우회 및 부하 분산을 위한 초간단 라운드로빈 구조


Overview
GPT API 쓰다 보면 429 Too Many Requests
에러 본 적 있을 거다. 이건 OpenAI API가 API Key 단위로 호출 한도를 두고 있기 때문이다. 그래서 실무에선 여러 개의 Key를 순환하면서 쓰는 구조가 필요하다.
그 중에서도 라운드로빈(Round-Robin) + 스레드 안전 처리를 적용한 구조가 가장 단순하면서 안정적이다.
Summary
여러 OpenAI API Key를 순환하며 사용
호출 한도(rate limit) 우회
트래픽 분산 및 API 부하 감소
다중 스레드 환경에서도 안정적인 처리
Sample Code
import threading
gpt_lock = threading.Lock()
def get_next_gpt_endpoint():
global gpt_last_index
with gpt_lock: # 동시성 제어: 하나의 스레드만 접근 허용
gpt_last_index = (gpt_last_index + 1) % len(gpt_endpoints)
endpoint = gpt_endpoints[gpt_last_index]
apikey = gpt_apikeys[gpt_last_index]
return endpoint, apikey
threading.Lock()
왜 쓰는가?
FastAPI + Uvicorn, Gunicorn, Flask 등 멀티스레드 환경에선
gpt_last_index
가 동시에 수정될 수 있음이걸 방지하려면 Mutex(상호 배제) 필요
with gpt_lock:
사용 시 블록 탈출과 동시에 자동으로release()
됨
라운드로빈 방식의 장점
Key 사용을 고르게 분산: 특정 키에 부하 몰리지 않음
단순함: 복잡한 상태 관리 없이 구현 가능
효율적: 무작위 선택보다 더 예측 가능하고 디버깅 쉬움
Conclusion
항목 | 효과 |
호출 한도 분산 | 여러 Key로 분산하여 limit 우회 |
부하 분산 | 특정 엔드포인트 집중 방지 |
안정성 | Race condition 방지 |
성능 | 병렬 환경에서도 안전하게 작동 |
Future Work
현재는 Key가 모두 정상이라고 가정한 구조다. 하지만 실전에서는 어떤 Key가 이미 사용량 초과 되었을 수도 있다.
Idea
각 Key의 상태/남은 quota 를 추적해서 사용
Redis 등에 Key 상태를 저장하고, “사용 가능 여부 기반으로 선택”
실패 횟수 누적 시 일정 시간 패널티 주기
Subscribe to my newsletter
Read articles from 김한결 directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
