Circuit 적용 고민

JUNE 15, 2024

현재 맡고 있는 서비스는 정부전자문서지갑 API에 대한 의존도가 높은데, 이 API는 장애가 잦은 편이다. 장애가 발생하면 서비스 응답 속도가 느려지고, 결국 사용자 경험이 나빠진다.
이런 문제를 해결하기 위해 Circuit Breaker 적용을 좀 더 세분화하여 진행했다.
기존에는 큰 기능 단위로만 Client Bean을 나누었지만, API 특성별로 더 세분화하여 대응하기로 했다.


1. Client Bean 세분화

일반적으로 외부 API를 호출하는 Client Bean은 host 단위로 생성한다. 하지만 장애가 잦은 API에 대해 더 정밀한 대응이 필요했기에, 장애 유형별, 구간별로 Client Bean을 추가 분리했다. 분리된 client들은 서로 중복으로 api path를 가질 수 있으며, 각 client 객체는 호출되는 시점이 다르다.

✔︎ 구조 개선

기존 구조 (AS-IS)

  • 개인 전자문서 지갑 관련 api 연동 client bean
  • 수취기관 관련 api 연동 client bean
  • 증명서 신청/제출 등 api 연동 client bean

개선된 구조 (TO-BE)

  • 장애가 자주 발생하는 api별 client bean 생성

    • 증명서 신청을 위한 부가정보 조회 api 전용 client bean
    • 사용자의 전자문서지갑 상태 조회 api 전용 client bean
  • 점검 유형 정하기 위한 구간별 client bean

    • 전자증명서 홈 진입 시 사용되는 api 전용 client bean
    • 증명서 신청 플로우에서 사용되는 api 전용 client bean
    • 증명서 보냄/받음 플로우에서 사용되는 api 전용 client bean
    • 내 증명서 확인 플로우에서 사용되는 api 전용 client bean
  • 그외 api 전용 client bean 생성

✔︎ 적용 효과

서비스 특성상 read timeout이 15초로 설정되어 있었고, 정부전자문서지갑 서버는 Timeout 에러가 자주 발생하는 상태였다.

Circuit Breaker가 오픈되면서

  • 15초 동안 기다리지 않고 빠르게 사용자에게 오류 페이지로 랜딩이 가능했다.

Client Bean을 세분화하면서

  • 어떤 플로우가 문제인지 좀 더 명확하게 파악할 수 있었다.
  • 점검 종류를 빠르게 파악이 가능하여 빠른 대응이 가능했다.

2. 불필요한 Pod 수 조정

Circuit Breaker는 각 파드에서의 에러율을 기준으로 동작하기 때문에, 트래픽 대비 Pod 수가 많으면 서킷이 제대로 동작하지 않는 문제가 있다.
현재 트래픽에 비해 설정된 Pod 수가 많았고, 적절한 Pod 개수로 조정하여 서킷이 정상적으로 동작할 수 있도록 했다.

✔︎ 적용 효과

  • 트래픽이 많지 않은 시간대 & 요일에도 Circuit Breaker가 정상적으로 동작하도록 개선됨.

3. Sliding Window 타입 결정

Resilience4j의 Circuit Breaker는 아래 2가지 Sliding Window 방식을 지원한다. 참고

Count-based Sliding Window

  • 요청 개수 단위로 데이터를 저장하고 집계하는 방식

Time-based Sliding Window

  • 요청 시간 단위로 데이터를 저장하고 집계하는 방식

처음에는 Time-based 방식을 고려했지만, Client Bean 세분화 및 낮은 트래픽을 가진 서비스의 특성을 고려하여 Count-based로 결정했다.

✔︎ 적용 효과

  • 트래픽이 낮은 늦은 밤, 새벽 시간대에도 서킷이 동작하도록 개선 됨

4. Fallback 적용 여부

✔︎ Fallback이란?

서비스를 차단한 경우, 예외를 발생시키는 대신 미리 준비된 동작을 실행하는 것을 의미한다.
즉, Circuit Breaker가 Open 상태일 때 요청을 에러로 응답하지 않고, 대체 응답을 제공하는 방식이다.

이번 작업의 목표는 빠르게 에러를 감지하고 사용자에게 안내하는 것이었기 때문에, Fallback을 적용하지 않고 즉시 에러 안내 페이지를 노출하도록 했다.


5. 최종 정리

  • 장애가 자주 발생하는 API별로 Client Bean을 세분화하여 장애 감지 속도를 높임
  • Pod 개수를 조정하여 Circuit Breaker가 정상 동작하도록 개선
  • 트래픽 특성을 고려해 Count-based Sliding Window 방식 적용
  • Fallback을 사용하지 않고 빠른 에러 안내 제공

작업 기록 블로그