수천 건짜리 문서를 임베딩해서 벡터DB에 넣는 배치 작업을 돌리는데 429가 계속 납니다. 재시도는 넣었어요. ThreadPool로 워커 20개 띄우고, 각 요청에 tenacity로 1초 고정 간격 재시도 3번을 걸어놨습니다.
그런데도 로그를 보면 초반 몇 초는 잘 나가다가 Rate limit reached ... please try again 가 우수수 뜨고, 재시도해도 또 터지는 게 반복됩니다. 재시도 로직이 있는데 왜 안 먹히는지 모르겠어요. 워커를 20개나 띄웠으니 처리량은 충분할 줄 알았는데 오히려 이게 문제인가 싶기도 하고요.
키는 유료 계정이고 결제도 되어 있는데, 제가 뭘 잘못 이해하고 있는 걸까요?
댓글 4
워커 20개가 동시에 계속 쏘면 분당 토큰 한도(TPM)랑 분당 요청 한도(RPM)를 지속적으로 넘깁니다. 재시도를 1초 뒤에 해도 그 1초 뒤에도 여전히 한도를 넘는 트래픽이 흐르고 있으니 또 429가 나는 거예요. 고정 간격 재시도는 진짜 일시적 오류(간헐적 5xx)엔 듣지만, 꾸준히 한도를 넘기는 상황엔 무의미합니다.
세 가지를 하세요. 첫째, 429 응답의 Retry-After 헤더를 읽어서 그 시간만큼 기다리세요. 서버가 언제 풀리는지 알려주는데 그걸 무시하고 1초 고정으로 때리고 있는 거예요. 둘째, 재시도는 지수 백오프에 지터를 섞어서. 셋째, 이게 핵심인데 동시성 자체를 낮추세요. 워커 20개는 지금 한도엔 과합니다.
근본적으로는 내가 쓰는 티어의 TPM에 맞게 처리량을 조절하는 문제예요. 실시간이 아닌 대량 임베딩이면 Batch API로 돌리는 게 정석입니다. 절반 가격에, 레이트리밋 걱정 없이 처리돼요.
요령은 요청 보내기 전에 토큰 수를 미리 세서(tiktoken으로) 예산에서 차감하는 겁니다. 남은 예산이 부족하면 잠깐 대기시켰다가 보내고요. 이렇게 하면 애초에 429가 거의 안 나고, 나더라도 Retry-After 존중하는 백오프가 받아주는 이중 안전장치가 됩니다. 트래픽이 정말 티어를 넘어서면 그건 코드가 아니라 한도 상향으로 풀 문제고요.