본문 바로가기
카테고리 없음

[Circuit Breaker] Circuit Breaker 패턴의 필요성

by hbIncoding 2025. 1. 20.

1. 서킷 브레이커란?

  • 쉽게 말하면 두꺼비 집과 같다.
    • 설정 이상의 전류가 흐르면 회로를 보호하기 위해 차단기가 작동된다.
    • 문제 상황에서 서버를 보호하기 위해 작동한다.
  • 서비스가 장애를 겪으면 클라이언트에게 유호한 응답을 줄 수 없다.
  • 적절한 조취를 취하지 않으면 서비스에 계속 요청을 보내고 우리는 한정된 자원(쓰레드, 메모리 등등)은 낭비 된다.
  • 이런 문제를 해결하기 위해 서킷 브레이거를 활용하게 된다.

2. 서킷 브레이커 구성

0) 서킷 브레이커는 크게 3가지로 구성되어 있다. Closed, Open, Half Open이 있다.

1) Closed

  • 아무런 문제가 없는 경우의 상태
  • 전기가 흐르기 위해서는 회로가 닫혀(closed)있어야 한다. 그래서 정상 상황이 closed 상태이다.
  • 서비스에 문제가 생겨 응답을 주지 못하는 상황이 발생한다.
    • 요청된 응답 중 예외 같은 오류코드가 발생한다.
    • 이때 서킷 브레이커가 open되기 위한 기준치가 존재한다.
    • 예를 들어 요청된 응답 중 설정된 비율 이상의 실패가 발생하면 서킷 브레이커가 open 되게 된다.

2) Open

  • 과한 전류가 흘러서 두꺼비 집이 내려가듯, 실패한 응답 비율이 설정 값보다 높아지면 서킷 브레이커가 open 되어 기존의 서비스로의 흐름을 막아버린다.
  • 그래서 일정 기간동안 요청이 들어오면 open으로 설정된 대체 서비스로 요청이 넘어간다.
  • 그렇다면 어떻게 다시 closed 상태로 돌아갈까?
    • 설정한 시간이 지나고 나면 바로 closed 상태로 복귀할 수 있다는 보장이 없다.
    • 서비스 장애로 부터 복구를 위해 요청을 대신 처리하고 있긴 하지만 기존 서비스의 동작 여부를 알 수 없다. 그래서 Half Open을 이용하여 기존 서비스가 복구 되었는지 확인한다.

3) Half Open

  • open에게 요청 받으면 기존의 서비스가 복구되었는지 확인하는 역할을 수행한다.
  • Half Open이 테스트를 하여 설정된 값을 기준으로 성공/실패 여부를 판단한다.
  • 서비스가 복구되었다고 판단하면 Closed 상태로 변경되고 기존 서비스 로직으로 돌아온다.
  • 만약 실패한다면 Open 상태로 돌아가게 되고, 일정 시간 이후에 다시 Half Open에게 요청이 들어온다.

3. 도입 배경

  • 현재 검색엔진의 메인은 엘라스틱 서치이다.
  • 하지만 엘라스틱 서치 설정에 익숙하지 않아, 서버가 불안정했다.
  • 불안정한 상태에서 서비스 전체를 중단시키기 보다는 다소 시간이 걸리더라도 기존에 개발했던 RDB를 이용한 검색을 사용하여 좀 더 나은 서비스를 제공하기 위해 도입했다.

4. Resilience4j 라이브러리

  • Java 진영에서 서킷 브레이커 라이브러리로는 Hystrix와 Resilience4j가 있다.
  • Hystrix는 넷플릭스에서 만든 오픈 소스 라이브러리인데 현재 deprecated 되어 Resilience4j를 사용했다.
  • 사용 예시
    • 아래 @CircuitBreaker의 정보를 보면 알 수 있듯, 실패시 fallbackMethod로 설정된 메서드를 실행하게 된다.
// ES 검색
@Transactional(readOnly = true)
@CircuitBreaker(name = "ElasticError", fallbackMethod = "keywordSearchBySql")
public BookListDto keywordSearchByElastic(FilterDto filter) {
   SearchHits<BookDto> search = elasticRepository.keywordSearchByElastic(filter);
   BookListDto result = resultToDto(search, filter);
   return result;
}

// Cursor 기반 페이징
@Transactional(readOnly = true)
public BookListDto keywordSearchBySql(FilterDto filter, Throwable t) {
   try {
      log.warn("keyword Elastic Down : " + t.getMessage());
      List<BookDto> books = bookDSLRepository.keywordSearchByCursor(filter);
      List<Object> cursors = getCursor(books, filter.getTotalRow(), filter.getSort());
      return new BookListDto(books, (String)cursors.get(0), (Long)cursors.get(1), filter.getPage(), false);
   } catch (Exception e) {
      log.warn("keyword Mysql SQLException : " + e.getMessage());
      return new BookListDto(new ArrayList<>(), null, null, null, false);
   }
}

 

  • 설정 파일 참고

 

5. 참고

1)서킷 브레이커 패턴 정리 : https://mangkyu.tistory.com/261

 

[디자인패턴] 서킷 브레이커 패턴(Circuit Breaker Pattern)의 필요성 및 동작 원리

이번에는 특히 MSA 환경에서 필수 패턴 중 하나인 서킷브레이커 패턴에 대해 알아보도록 하겠습니다. 1. 서킷 브레이커 패턴(Circuit Breaker Pattern)의 등장 및 개념 [ 서킷 브레이커 패턴(Circuit Breaker P

mangkyu.tistory.com

2)Resilience4j 공식 문서 : https://godekdls.github.io/Resilience4j/timelimiter/#google_vignette