서킷 브레이커 복구의 동시성 문제
H ALF-OPEN 상태에서 하위 서비스 복구 여부를 확인하기 위한 프로브 요청 시, 동시성 환경에서는 여러 워커가 동시에 프로브를 시도하며 다음과 같은 문제가 발생합니다.
1. Thundering Herd (동시 다발적 요청)
-
문제: 쿨오프 기간 만료 후 수많은 워커가 동시에 HALF-OPEN 상태로 전환되어 하위 서비스에 프로브 요청을 보냅니다.
-
결과: 불안정한 서비스에 과도한 부하를 주어 복구 중인 서비스를 다시 실패 상태로 만들거나, 서킷 브레이커가 막으려던 캐스케이딩 실패를 복구 테스트 중에 유발할 수 있습니다.
2. Racing Decisions (경쟁적 결정)
-
문제: 동시에 프로브를 보낸 워커들이 서비스의 불안정성으로 인해 다른 결과를 받고, 각기 다른 상태(CLOSED/OPEN)로 전환을 시도합니다.
-
결과: 네트워크 타이밍에 따라 최종 상태가 결정되어 서비스 상태에 대한 일관성 없이 서킷 브레이커 상태가 불안정하게 변경됩니다. 각 워커의 결정은 개별적으로 옳아 보여 디버깅이 어렵습니다.
해결책: 전체 프로브 직렬화
이러한 문제를 해결하기 위해, 상태 전환을 넘어 전체 프로브 시퀀스를 직렬화해야 합니다.
-
방법: 하나의 워커가 락을 획득하여 프로브, 평가, 상태 전환, 락 해제까지의 전체 과정을 독점적으로 수행합니다.
-
다른 워커의 동작: 락이 걸려 있는 동안 다른 워커가 프로브를 시도하면, 즉시 “다른 워커가 프로브 중이므로 OPEN으로 간주하라”는 응답을 받아 요청을 즉시 폴백 처리합니다.
-
효과:
- Thundering Herd 방지: 단 하나의 프로브 요청만 하위 서비스에 도달하며, 나머지 요청은 즉시 폴백됩니다.
- Racing Decisions 방지: 단일 워커만이 관찰하고 결정하므로, 상태 전환 충돌 없이 일관된 서비스 상태를 유지합니다. 이는 스레드 환경에서는 Mutex를, 분산 시스템에서는 Redis 락과 같은 분산 락을 사용하여 구현할 수 있습니다.