MSA 학습 - 서킷 브레이커

2025. 9. 24. 23:16·Back-End

이번에는 MSA 서비스를 운영하면서 발생할 수 있는 장애 상황 대한 방법을 학습해봤다. 이전에 FeignClient를 이용한 로드밸런싱에 대해서 다뤘는데, MSA 환경에서는 로드밸런싱만큼이나 중요한 것이 바로 `장애 전파 방지`이다. 아무리 로드밸런싱을 잘 구성해도 특정 서비스가 장애가 나면 연쇄적으로 다른 서비스들까지 영향을 받을 수 있기 때문이다. 이런 상황에서 서킷 브레이커 패턴이 필요한 이유와 Spring Cloud에서 제공하는 Resilience4j를 이용한 구현 방법을 정리해보려고 한다.

 

서킷 브레이커란?

서킷 브레이커는 전기의 회로 차단기에서 착안한 개념이다. 전기 회로에서 과부하가 걸리면 차단기가 작동해서 전체 시스템을 보호하는 것처럼, 마이크로서비스에서도 특정 서비스에 장애가 발생했을 때 해당 서비스로의 호출을 차단해서 전체 시스템을 보호하는 패턴이다.

 

기본적으로 서킷 브레이커는 3가지 상태를 가진다.

  • CLOSED: 정상 상태로 모든 요청이 통과한다. 실패율이 설정된 임계값(ex. 50%)을 초과하면 OPEN 상태로 전환된다.
    • 예를 들어 최근 5번의 호출 중 3번이 실패하면 실패율이 60%가 되어 OPEN 상태로 변경
  • HALF_OPEN: 테스트 상태로 장애 발생 이후 일부 요청만 통과시켜 서비스 복구 여부를 확인한다
  • OPEN: 장애 상태로 모든 요청을 차단하고 즉시 예외를 반환한다.

여기서 헷갈리면 안되는 부분은 OPEN이 장애 상황인 것이고, CLOSED가 정상인 것이다. 실제 회로에서도 CLOSE상태가 되어야 전류가 흐르고 정상적인 상태가 되니까 이러한 연관법으로 생각하면 헷갈리지 않을 수 있다.

 

왜 서킷 브레이커가 필요할까?

MSA 환경에서 서비스 간 호출은 필수적이다. 예를 들어 주문 서비스가 결제 서비스를 호출하고, 결제 서비스가 다시 사용자 서비스를 호출하는 식으로 의존성이 복잡하게 얽혀있다. 이때 사용자 서비스에 장애가 발생하면 어떻게 될까?

 

  1. 사용자 서비스 응답 지연/실패
  2. 결제 서비스에서 사용자 서비스 호출 시 타임아웃 대기
  3. 결제 서비스 스레드 풀 고갈
  4. 주문 서비스에서 결제 서비스 호출 시 타임아웃 대기
  5. 주문 서비스 스레드 풀 고갈 등 주문 서비스까지 장애가 전파됨

이런 연쇄 장애를 방지하기 위해 서킷 브레이커가 필요한 것이다.

 

서킷 브레이커 적용

서킷 브레이커 의존성 추가

우리가 스프링에서 서킷 브레이커를 적용하기 위한 의존성은 2개로 나뉜다.

`org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j`와
`io.github.resilience4j:resilience4j-spring-boot3:2.2.0`이다.

`org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j` 의 경우에는 Spring Cloud에서 제공하는 추상화 레이어로써 `CircuitBreakerFactory`라는 인터페이스를 통해 프로그래밍 방식으로 서킷 브레이커를 생성하고 사용한다.

 

하지만 `io.github.resilience4j:resilience4j-spring-boot3:2.2.0`의 경우 @CircuitBreaker, @Retry, @TimeLimiter 등의 어노테이션 기반 사용을 하며 application.yml을 통해서 설정을 진행할 수 있다.

 

나는  `io.github.resilience4j:resilience4j-spring-boot3:2.2.0`을 사용할 생각이다.

어제 진행했던 auth-service와 user-service에 이어서 작성을 해보겠다.

우선 user-service에서 장애 발생 시 auth-service로 전파되지 않게 해야 하기 떄문에 user-serivce 쪽에 의존성을 추가해줬다.

 

application.yml 설정

 

 

Fallback 설정

우선 장애가 발생했으면, 이러한 장애가 발생했다는 응답을 다른 서비스에게 전달할 수 있어야 한다. 우리는 장애 전파를 단순 응답으로 하는게 아니라 서킷 브레이커를 이용해 fallback 로직을 제공해 로그 등을 추적하거나 남길 수 있다.

그냥 try-catch 구문 등으로 예외 발생 시 예외 응답을 보내는 식으로 해도 되지 않을까? 라는 생각이 들 수 있지만, try-catch의 경우 로직이 흘러가다가 오류가 발생하는 시점에서 예외가 발생한다. 하지만 서킷브레이커를 이용하면 OPEN 상태일 경우 바로 fallback 메소드를 반환할 수 있기 때문에, 쿼리 조회, 비즈니스 로직 수행, 불필요한 시스템 자원 낭비 등을 방지할 수 있다.

 

먼저 userService에 로직을 설정하는데, userId가 error로 들어오면 장애를 발생시키고 나머지 경우 정상적으로 문자열을 반환한다.

또한, 상태가 CLOSED -> OPEN -> HALF_OPEN -> CLOSE로 잘 동작하는지 추적을 위해 로그를 추적할 수 있게 작성했다.

그럼 이전과 같이 포스트맨으로 테스트를 해보겟다.

 

auth-service에 보내도 FeignClient를 통해서 user-service의 로직을 잘 수행하고 있다.

 

에러를 발생시켰더니 정상적으로 fallback method를 통하는 모습을 볼 수 있었다.

 

5번째 에러가 발생하는 순간 OPEN 상태로 전환해 기존의 메소드가 실행되지 않고 바로 fallback 메소드로 가는 설정이 진행되었다.

이 때, 그럼 userId로 error 가 아니라 1을 넣는다면 기존처럼 `User ID: 1` 이 아니라 `Fallback User ID: 1`이 나오게 될 것이다.

 

우선 1을 넣어보았더니 내가 원하는 폴백이아니라 User ID가 정상적으로 나오고 HALF_OPEN 상태로 변경되었다. 에러를 10번정도 진행시켜보겠다.(내가 글을 작성하는 동안 20초가 지나 application.yml 에서 설정한 시간이 넘어 HALF_OPEN이 되어 정상 응답이 나왔던 것이었다.)

 

다시 HALF_OPEN -> OPEN이 되었고

정상적인 값을 넣었음에도 fallback 메소드가 실행된 것을 알 수 있었다.

 

순서대로 내용을 정리해보면 다음과 같다.

 

  • 실행 직후 CLOSED 상태 : 서킷브레이커가 동작하지 않음.
  • 계속해서 호출을 감지하고 있다가 application.yml에 설정한 것 처럼 5번의 호출 이상 + 50% 이상 실패 시 OPEN으로 변경
    • 슬라이딩 윈도우는 항상 최신 N개의 호출만 계산함 
    • 초기에 정상응답 10번 + error 응답 3번 -> 슬라이딩 윈도우 최근 5번 중 3번 실패(60%) -> OPEN
    • 실행 직후 4번의 error 응답 -> 최소 호출 수 5번 미충족 -> 동작하지 않음
  • 20초 동안 fallback 메소드를 계속해서 보내다가 20초가 지나는 시점에서 OPEN -> HALF_OPEN 으로 변경
  • HALF_OPEN 상태에서 최대 3번의 호출을 허용
    • 성공/성공/성공 → 0% 실패율 → CLOSED
    • 실패/실패 → 100% 실패율 → 즉시 OPEN (3번째 호출 안함)
    • 성공/실패/성공 → 33% 실패율 → CLOSED
    • 실패/성공/실패 → 67% 실패율 → OPEN
    • 성공/실패/실패 → 67% 실패율 → OPEN

'Back-End' 카테고리의 다른 글

재고 관리 문제 해결(동시성 및 DB 동기화 전략에 대해)  (0) 2026.01.07
MSA 학습 - API Gateway  (0) 2025.09.25
MSA 학습 - 로드밸런싱(FeignClient, Ribbon)  (0) 2025.09.23
MSA 학습 - Spring Cloud와 Eureka  (0) 2025.09.22
비동기 메시징 방식(RabbitMQ vs Kafka)  (0) 2025.09.19
'Back-End' 카테고리의 다른 글
  • 재고 관리 문제 해결(동시성 및 DB 동기화 전략에 대해)
  • MSA 학습 - API Gateway
  • MSA 학습 - 로드밸런싱(FeignClient, Ribbon)
  • MSA 학습 - Spring Cloud와 Eureka
dev_Mins
dev_Mins
  • dev_Mins
    천천히 빠르게!
    dev_Mins
  • 전체
    오늘
    어제
    • 분류 전체보기 (49)
      • 42Seoul (2)
      • Back-End (20)
        • Spring (8)
      • Project (14)
        • PickLab (3)
      • 끄적끄적 (3)
      • Algorithm (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    스프링 jwt
    MSA Gateway
    Spring
    Kafka
    로드밸런서
    42seoul
    주문 서비스
    재고 서비스
    스프링
    Spring Cloud
    MSA
    42서울
    로드밸런싱
    Spring Security
    Spring Data JPA
    Spring Boot
    Servcie Discovery
    AWS
    스프링 게이트웨이
    JWT
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dev_Mins
MSA 학습 - 서킷 브레이커
상단으로

티스토리툴바