← 문제로

25. 장애 격리·복원력 패턴: 서킷 브레이커·벌크헤드·타임아웃·재시도·백오프·부하 차단

난이도 상
내 답안
모범답안

난이도: 상

1. 타임아웃 — 복원력의 출발점

  • 타임아웃 없는 호출의 재앙: 다운스트림이 응답하지 않으면 호출 스레드/커넥션이 무한 대기한다. 요청이 계속 들어오면 스레드풀·커넥션풀이 전부 대기 상태로 고갈되고, 그 서비스와 무관한 요청까지 처리 못 해 전체 장애가 된다. 즉 한 곳의 지연이 자원 고갈을 통해 전파된다.
  • 연결 타임아웃 vs 읽기 타임아웃: 연결(TCP 핸드셰이크/풀 획득) 대기 상한과, 요청 보낸 뒤 응답 바이트 대기 상한은 별개로 걸어야 한다. 둘 다 없으면 어느 단계든 무한 대기 가능.
  • 데드라인 전파: 최상위 요청에 "전체 예산"(예: 200ms)을 주고, 각 하위 호출에 남은 예산을 전달한다. 하위가 이미 지난 데드라인을 보면 즉시 포기 → 헛된 작업(만료된 요청 처리)을 막는다.

2. 재시도 — 멱등성·백오프·지터·예산

  • 재시도 가능 조건: 일시적 오류(타임아웃, 5xx, 커넥션 리셋)만. 그리고 연산이 멱등하거나 멱등키로 중복을 흡수할 수 있어야 한다. 결제 "차감"을 무턱대고 재시도하면 이중 청구.
  • 지수 백오프 + 지터: 재시도 간격을 1,2,4…로 늘리고 무작위 지터를 더한다. 지터가 없으면 많은 클라이언트가 동시에 실패→동시에 재시도해 재시도 폭풍(동기화된 부하 스파이크)으로 회복 중인 서비스를 다시 죽인다.
  • 재시도 예산: 전체 트래픽 중 재시도가 차지하는 비율에 상한(예: 원요청의 10%)을 둔다. 장애 시 재시도가 정상 트래픽의 몇 배로 증폭되는 것을 막는다. 재시도 총량·시도 횟수 모두 제한.

3. 서킷 브레이커

  • 상태:
    • Closed: 정상. 호출을 통과시키며 실패율/지연을 집계.
    • Open: 실패율이 임계치를 넘으면 열려서, 이후 호출을 **즉시 실패(fail-fast)**시킨다 (다운스트림을 때리지 않음). 자원 고갈·연쇄 장애를 끊는다.
    • Half-Open: 열림 시간(cooldown) 후 소수의 프로브 요청만 통과시켜 회복을 확인. 성공하면 Closed로, 실패하면 다시 Open으로.
  • 연쇄 장애 차단: Open 상태에서 fail-fast 하므로 호출 스레드가 죽은 서비스에 묶이지 않고, 타임아웃 대기조차 하지 않는다 → 풀 고갈 방지.
  • 튜닝: 실패율 임계·최소 표본 수(적은 표본으로 성급히 열지 않게)·열림 시간·half-open 프로브 수. 지연 기반(느린 응답도 실패로)도 유용.
  • 재시도와의 조합: 재시도는 서킷 안쪽(단일 호출의 일시 오류 흡수), 서킷은 바깥쪽에서 전체 의존성의 건강을 판단. 서킷이 Open이면 재시도하지 말고 즉시 폴백. 둘을 잘못 조합하면 재시도가 서킷 통계를 오염시키거나 폭풍을 키운다.

4. 벌크헤드 격리

  • 배의 격벽처럼, 의존성별로 자원 풀(스레드/커넥션/세마포어)을 분리한다. 결제 호출용 풀과 전투 로직용 풀을 나누면, 결제가 느려져 결제 풀이 고갈돼도 전투 처리 풀은 멀쩡하다.
  • 세마포어 기반 벌크헤드는 "이 의존성에 동시 N개까지만" 제한해, 한 의존성이 전체 동시성을 독식하지 못하게 한다. 서킷 브레이커가 "언제 끊을지"라면 벌크헤드는 "얼마나 격리할지".
  • 게임서버 예: 외부 결제/랭킹/추천 같은 저신뢰·고지연 의존성은 별도 풀·별도 스레드로 격리하고, 실시간 틱/전투는 절대 그 풀을 공유하지 않게 설계.

5. 부하 차단·우아한 열화·폴백

  • 부하 차단(load shedding): 과부하 시 낮은 우선순위 요청을 일찍 거부(429/큐 진입 거부)해 핵심 기능을 지킨다. 무제한 큐잉은 메타안정 장애를 부르므로 유한 큐 + 조기 거부가 낫다. 만료된(데드라인 지난) 요청은 처리 전에 버린다.
  • 우아한 열화: 랭킹/추천/친구 추천처럼 없어도 게임이 되는 기능은 장애 시 꺼도 되고, 로그인/ 전투/저장처럼 핵심인 기능은 지킨다. 기능별 우선순위를 명시.
  • 폴백: 의존성이 죽으면 캐시된 마지막 값·기본값·근사값으로 대체(예: 실시간 랭킹 대신 N분 전 스냅샷, 추천 대신 인기 목록). 폴백은 "그럴듯한 안전한 기본"이어야 하고, 폴백 중임을 관측(메트릭)해야 한다.
  • 전체 그림(조합): 모든 원격 호출에 타임아웃/데드라인 → 일시 오류는 백오프+지터 재시도(예산 내) → 의존성 건강이 나쁘면 서킷 브레이커가 Open으로 fail-fast → 자원은 벌크헤드로 격리 → 과부하면 부하 차단 + 폴백/열화로 핵심만 지킨다. 그리고 이 모든 상태(타임아웃율·재시도율·서킷 상태·폴백율)를 관측·알람으로 노출한다.

면접 포인트

  • 타임아웃 부재 → 풀 고갈 → 연쇄 장애의 인과, 데드라인 전파의 이점.
  • 재시도의 멱등성 전제와 지터 없는 재시도 폭풍, 재시도 예산.
  • 서킷 브레이커 3상태와 벌크헤드의 역할 분담("끊기" vs "격리"), 부하 차단·폴백으로 핵심 기능 우선 보호.