// note
LLM 호출 한도 — 인스턴스별 카운터로는 못 막음
- 여러 사용자가 동시에 쓰는 LLM 어시스턴트 서비스의 백엔드
증상
- 사용자가 몰리면 LLM 공급자 한도(분당 요청 수·분당 토큰 수)에 걸려 호출이 실패
- 서버 각각은 여유가 있다고 판단하는데도 발생
원인
- 한도 카운터가 프로세스 메모리에 있음 — 인스턴스가 3대면 각자 전체의 1/3만 보고 "여유 있음"으로 판정 → 합치면 초과
- 여유를 확인하는 시점과 사용량을 기록하는 시점이 벌어져, 그 사이에 도착한 요청이 같은 여유를 다시 읽고 통과
조치
- 한도 상태를 Redis로 이동 — 인스턴스가 몇 대든 한 곳에서 셈. 슬라이딩 윈도로 최근 1분치만 남기고 지나간 기록은 버림
- 확인과 기록을 Lua 스크립트로 묶어 Redis 안에서 한 번에 실행 — 네트워크 왕복 사이에 다른 요청이 끼어들 틈을 없앰
- 초과분은 거부 대신 대기열 — sorted set에 도착 시각을 score로 넣어 FIFO 유지. 순위를 조회해 대기 순번을 WebSocket으로 통지
- 대기열 소진은 이벤트 구독으로 — 큐 키의 변경 알림을 구독해 워커가 즉시 깨어나고, 알림 유실에 대비해 주기적 폴링을 폴백으로 병행
- 사용량은 선차감 후 정산 — LLM 출력 길이를 미리 알 수 없어 최대치로 자리를 잡아둔 뒤, 응답이 끝나면 실측으로 보정
결과
- 한도 초과가 실패가 아니라 대기로 바뀌어 사용자 재시도가 사라짐
- 인스턴스를 늘려도 전역 한도가 유지됨
순번·정산 결과를 사용자 소켓으로 되돌리는 쪽 → 수평 확장 WebSocket 세션 라우팅