주문 서버가 결제사 API를 부르는데 가끔 타임아웃이 난다. 자동으로 몇 번 더 시도할지, 아니면 바로 실패를 돌려주고 사용자에게 알릴지 정해야 한다.
언제: 에러가 가끔(1% 미만) 튀는 일시적인 네트워크 문제이고, 같은 요청을 두 번 보내도 안전한(멱등) 호출일 때. 대부분의 조회성 호출이 여기에 해당한다.
비용: 재시도하는 만큼 응답이 느려진다. 그리고 장애가 길어지면 재시도가 트래픽을 2~3배로 불려서, 이미 힘들어하는 다운스트림 서버를 더 밟게 된다.
언제: 다운스트림이 일시적 흔들림이 아니라 진짜 죽었을 때(5xx가 몇 분째 지속), 또는 결제처럼 두 번 실행되면 사고가 나는 쓰기 호출일 때. 빨리 실패시키고 회로를 열어 다운스트림이 회복할 시간을 준다.
비용: 회로가 열려 있는 동안에는 멀쩡한 요청도 같이 거절된다. 에러율 임계값과 열어두는 시간을 잘못 잡으면 오탐으로 자꾸 끊기고, 서킷브레이커라는 운영해야 할 부품이 하나 더 늘어난다.
기본은 멱등한 호출에만 백오프+지터 걸어 2~3번 재시도하는 평범한 방법으로 시작한다. 다운스트림 5xx가 몇 분째 지속되거나 재시도 때문에 호출량이 배로 불어나는 게 보이면, 그때 서킷브레이커를 넣고 바로 실패시키는 쪽으로 바꾼다. 결제 같은 비멱등 쓰기는 멱등키를 붙이기 전까지는 재시도 없이 바로 실패가 기본이다.
- 다운스트림 5xx/타임아웃이 순간 스파이크가 아니라 5분 이상 지속 — 일시 장애가 아니라는 신호
- 재시도 포함 호출량이 원래 트래픽의 2배 이상 — 재시도 폭풍으로 장애를 키우고 있는 중
- p99가 호출자 타임아웃(예: 1초)의 80%를 넘음 — 재시도 한 번 들어갈 시간 예산이 없음
- 같은 주문에 결제가 2건 찍힘 — 비멱등 호출에 재시도가 걸려 있다는 뜻, 즉시 중단
🔧Spring Retry (@Retryable + backoff)resilience4j CircuitBreakerIdempotency-Key headerPrometheus error-rate / p99 alert
“I default to a few jittered retries on idempotent calls, then fail fast — retries just amplify a real outage.”
checking microphone…