장애는 막을 수 없다. 대신 장애가 전파되지 않게 막거나, 부분적으로만 동작하거나, 빠르게 회복하도록 설계할 수 있다. 그게 Reliability Patterns의 목적이다.
문제가 생긴 서비스로의 요청을 자동으로 차단해서 장애 전파를 막는 패턴이다.
| 상태 | 설명 |
|---|---|
| Closed | 정상. 요청이 통과된다 |
| Open | 차단. 요청을 바로 실패 처리한다 |
| Half-Open | 일부 요청만 통과시켜서 복구됐는지 확인한다 |
실패율이 임계값을 넘으면 Open 상태가 된다. 일정 시간 후 Half-Open으로 전환되고, 일부 요청이 성공하면 Closed로 복귀한다. 계속 재시도하다가 시스템 전체가 느려지는 걸 막는 게
핵심이다.
일시적인 장애에서 재시도하는 패턴이다. 무작정 재시도하면 서버에 부하가 몰리기 때문에 재시도 간격을 점점 늘린다.
1차 재시도: 1초 후
2차 재시도: 2초 후
3차 재시도: 4초 후
여기에 Jitter(무작위 편차)를 추가하면 여러 클라이언트가 동시에 재시도하는 Thundering Herd를 방지할 수 있다. Jitter가 없으면 1000개 클라이언트가 전부 동시에 재시도해서 서버
부하가 급등한다.
배의 격벽처럼 서비스 리소스를 격리해서 한 곳의 장애가 전체로 번지지 않게 막는 패턴이다.
결제 API와 조회 API가 같은 스레드 풀을 쓰면 조회 요청이 폭발할 때 결제도 느려진다. Bulkhead를 적용하면 스레드 풀을 분리해서 서로 영향을 안 준다.
Circuit Breaker와 헷갈리기 쉬운데 구분 기준은 이렇다.
Circuit Breaker: 문제 있는 서비스로 요청이 가는 걸 차단
Bulkhead: 서비스 간 리소스를 격리해서 영향이 번지는 걸 차단
응답을 무한정 기다리지 않고 일정 시간 후 실패 처리하는 패턴이다. Timeout이 없으면 느린 서비스 하나가 전체 요청을 블로킹한다.
일부 기능이 실패해도 핵심 기능은 동작하게 유지하는 패턴이다.
추천 서비스가 죽어도 상품 목록은 보여준다
실시간 데이터를 못 가져오면 캐시된 데이터를 보여준다
전부 아니면 전무(All or Nothing)가 아니라, 부분적으로라도 동작하는 것이 목표다.
| 패턴 | 목적 |
|---|---|
| Circuit Breaker | 장애 전파 차단 |
| Retry + Backoff | 일시적 장애 극복 |
| Bulkhead | 장애 격리 |
| Timeout | 블로킹 방지 |
| Graceful Degradation | 부분 동작 유지 |
이 패턴들은 하나만 쓰는 게 아니라 조합해서 쓴다. 실제 시스템에서는 Timeout + Circuit Breaker + Graceful Degradation이 같이 적용되는 경우가 많다.