티스토리 뷰
이번에는 특히 MSA 환경에서 필수 패턴 중 하나인 서킷브레이커 패턴에 대해 알아보도록 하겠습니다.
1. 서킷 브레이커 패턴(Circuit Breaker Pattern)의 등장 및 개념
[ 서킷 브레이커 패턴(Circuit Breaker Pattern)의 등장 ]
개발을 하다 보면 외부 API를 호출해야 하는 경우가 있다. 특히나 전체적인 시스템 구성이 MSA로 되어 있다면 다른 서비스를 호출하는 경우가 매우 빈번하다. 문제는 서버들에 장애가 발생할 수 있다는 점인데, 호출한 다른 서비스에 장애가 발생했다면 장애가 전파되어, 해당 서비스까지 문제가 발생할 수 있다. 또한 장애가 발생한 서버에 계속 요청을 보내는 것은 장애 복구를 힘들게 만든다.
그래서 장애가 발생한 서비스를 탐지하고, 요청을 보내지 않도록 차단할 필요가 생기게되었다. 위에서 설명한 다른 서비스의 장애가 전파되는 과정 등은 아래에서 다시 한번 자세히 살펴보도록 하자.
[ 서킷 브레이커 패턴(Circuit Breaker Pattern)이란? ]
외부 서비스에 의한 문제를 방지하기 위해 등장한 것이 서킷 브레이커 패턴이다. 서킷 브레이커 패턴은 Release It 이라는 책에서 처음 소개된 디자인 패턴으로, 문제가 발생한 지점을 감지하고 실패하는 요청을 계속하지 않도록 방지한다. 이를 통해 시스템의 장애 확산을 막고, 장애 복구를 도와주며 사용자는 불필요하게 대기하지 않게 된다. 즉, 서킷 브레이커 패턴은 클라이언트 측면에서 장애를 방지하기 위한 도구로써, 실패할 수 있는 작업을 계속 시도하지 않도록 방지한다.
2. 서킷 브레이커 패턴(Circuit Breaker Pattern)의 동작 원리
[ 실제 회로 차단기의 동작 원리 ]
일반적으로 회로는 닫혀있어서 전류가 흐르게 된다. 그래서 전원이 켜진 상태라면 다음과 같이 전구에 불이 들어온다. 하지만 전구에 문제가 생겨서 계속해서 전류가 흐르면 위험한 상황이 되었다고 하자. 즉, 전구에 과부하가 걸려 문제가 생길 수 있는 것이다.
그럴때 회로 차단기는 자동으로 회로를 열고 차단해 전구에 전류가 흐르지 않도록 조치하여 위험한 상황을 방지해준다. 여기서 회로를 연다는 것은 좋은 상황이 아니라, 문제가 생겨 흐름을 차단하는 것이므로 혼동하지 않도록 주의해야 한다. 이렇듯 문제 상황을 감지하고, 자동으로 방지해주는 기능을 수행하는 것이 회로 차단기인데, 서킷 브레이커 패턴은 이러한 회로 차단기로부터 아이디어를 얻어 만들어졌다.
[ 서킷 브레이커 패턴(Circuit Breaker Pattern)의 동작 원리 ]
서킷 브레이커의 3가지 상태
실제 회로를 기준으로 전구가 외부 API 또는 Callee에 해당하고, Power Source가 클라이언트(다른 서버를 호출하는 서버) 또는 Caller에 해당한다. 그리고 회로 차단기에는 크게 Closed, Open, Half Open 3가지 상태가 존재하는데, 각각의 상태를 정리하면 다음과 같다.
Closed | Open | Half Open | |
상황 | 모든 것이 정상인 상황 | 외부(Callee)에 장애가 발생한 상황 | Open 상태가 되고 일정 시간이 지난 상황 |
요청 | Open 상태가 되고 일정 시간이 지난 상황 | 외부(Callee)로의 요청을 차단하고 바로 에러를 받음 | 외부(Callee)로의 요청을 차단하고 바로 에러를 받음 |
상태 전이 | 외부(Callee)로의 요청을 차단하고 바로 에러를 받음 | 특정 시간이 지나면 Half Open 상태가 됨 | 일부 허용된 요청들이 성공한 경우 Closed 상태로, 실패인 경우 Open 상태로 변경 |
여기서 외부에 장애가 발생했는지 판단하는 기준은 크게 2가지가 있는데, 각각의 정해진 임계치가 넘어갈 경우 요청이 차단된다.
- slow call: 기준 시간보다 오래 걸린 요청
- failure call: 실패하거나 오류를 응답받은 요청
그러므로 이러한 기준을 적용하여 다음과 같은 규칙을 만들 수 있다.
- 특정 요청이 3번 연속 실패할 경우 요청을 차단한다.
- 특정 요청이 5번 연속 n초 이상 시간초과 할 경우 요청을 차단한다.
- 차단했던 요청이 3번 연속 성공 할 경우 요청을 전송한다.
서킷 브레이커의 동작 방식 예시
- 일반적으로 외부 서버는 정상 실행중이므로, 서킷이 닫혀있고 요청이 정상적으로 전달됨
- 외부 서버에 장애 발생
- 요청이 계속해서 실패하고, 회로가 Open 상태가 됨
- 이후의 요청들은 더 이상 전달되지 않고 차단되며, 빠르게 에러 또는 실패 응답을 반환함
- 이후에 외부 서버가 정상적으로 복구됨
- 회로가 Open 상태가 된지 특정 시간이 지나고, Half Open 상태로 변경됨
- 일부 요청들이 외부 서버로 전달되고, 응답에 성공하여 Closed 상태됨
- 모든 요청들이 정상적으로 전달됨
Open 상태가 되면 특정 시간이 지나야 Half Open 상태가 된다. 만약 Half Open 상태가 되었는데도 외부 서버가 복구되되지 않았다면, 요청들은 실패해서 다시 Open 상태로 변경될 수도 있다. 여기서 중요한 것은 이러한 상태 변경이 자동으로 수행된다는 것이며, 상태 전이를 위한 시간들은 시스템 내부에서 관리되므로 대부분 타임아웃과 관련된 모니터링 시스템을 제공해준다.
3. 서킷 브레이커 패턴(Circuit Breaker Pattern)의 장점 및 필요성
[ 서킷 브레이커 패턴(Circuit Breaker Pattern)의 장점 및 필요성 ]
- 장애 감지 및 격리
- 자동 시스템 복구
- 빠른 실패 및 고객 응답
- 장애 서비스로의 부하 감소
- 장애 대안 커스터마이징
장애 감지 및 격리
만약 장애가 발생한 서비스를 호출한다면 요청이 타임아웃만큼 대기하게 되고, 쓰레드와 메모리 및 CPU 등의 자원을 점유하게 된다. 이것은 결국 시스템 리소스를 부족하게 만들어 장애를 유발할 수 있다. 장애가 발생한 것은 다른 서비스인데, 장애가 전파되는 것이다. 서킷 브레이커 패턴은 장애가 발생한 서비스를 감지하고, 더 이상 요청을 보내지 않도록 차단함으로써 장애를 격리시켜 준다. 그래서 장애가 발생한 기능 외의 다른 기능들은 동작하게 하여 시스템의 안정성을 높일 수 있다.
이미지 출처: https://junhyunny.github.io/spring-boot/spring-cloud/msa/design-pattern/msa-circuit-breaker-pattern/
자동 시스템 복구
서킷 브레이커는 요청이 차단되면 해당 서비스가 정상인지 주기적으로 검사한다. 그리고 해당 서비스가 복구되었다면 차단이 해제되고, 정상적으로 요청을 보내게 된다. 이러한 부분들은 시스템이 자동으로 해주므로 개발자들이 신경쓰지 않아도 된다. 대부분 타임아웃 등을 위한 모니터링 기능까지 제공하며, 서킷 브레이커가 모든 연동에 적용되면 대시보드를 통해 전체 시스템들의 연동 현황까지 모니터링 가능하다.
빠른 실패 및 고객 응답
만약 다른 서비스가 문제있음을 알 수 있다면, 타임아웃 동안 기다리며 자원을 낭비할 필요가 없다. 그래서 빠르게 장애를 탐지하는 것이 중요한데, 서킷브레이커 패턴을 적용하면 가능한 빠르게 실패를 반환하고, 고객에게 응답을 전달할 수 있다.
장애 서비스로의 부하 감소
외부 서비스가 완전히 죽지는 않았는데, slow query 등의 이유로 사용 가능한 쓰레드가 더 남아있지 않을 수도 있다. 이때 계속 요청을 보내는 것은 외부 서비스의 상황을 악화시켜 장애를 유발시킬 수 있다. 그러므로 해당 서비스가 안정을 찾도록 요청을 멈추는 것이 좋은데, 서킷 브레이커를 사용하면 해당 서비스는 더 이상의 요청이 유입되지 않아 장애를 복구할 수 있는 기회를 얻을 수 있다.
장애 대안 커스터마이징
외부 서비스에서 장애가 발생했다면 원하는 데이터를 얻지 못할 수 있다. 이때 아무런 대응책이 없다면 해당 서비스 역시 장애가 발생하게 된다. 서킷 브레이커를 적용하면, 장애 대안을 커스터마이징 할 수 있는데, 예를 들어 다른 소스로부터 값을 얻어오거나, 서킷 브레이커가 자체적으로 캐싱해 둔 값으로 응답하는 등 다양한 방법을 적용할 수 있다. 그러면 외부에 장애가 발생해도 문제없이 서비스를 운영할 수도 있다.
국내 대부분의 서비스들은 스프링 MVC 기반으로 되어있다. 스프링 MVC는 멀티 쓰레드 기반으로 동작하므로 장애가 있는 서비스를 호출하면 쓰레드 점유에 의한 응답 지연이 발생하기 쉽다. 그래서 장애가 전파되기 쉬운데, 서킷 브레이커를 사용하면 빠르게 장애가 발생한 서버로의 요청을 차단하고 이를 해결할 수 있다. 심지어 대안책을 적절히 마련한다면 정상적인 서비스 운영까지 가능하다. 물론 서킷 브레이커를 도입한다면 서킷 브레이커의 상태 및 히스토리 관리 등을 위한 추가 비용이 발생한다. 하지만 오늘날 서킷 브레이커는 안정적인 서비스 운영을 위한 필수 패턴이므로 반드시 적용해야 한다.
[ Java 진영의 서킷 브레이커 라이브러리 ]
자바 진영의 서킷 브레이커 라이브러리로는 크게 Hystrix와 Reslience4J가 존재한다. Hystrix는 넷플릭스에서 만든 오픈소스인데, deprecated되었으므로 reslience4j를 사용하면 된다. Hystrix에서도 오픈소스인 resilience4j 사용을 권장하고 있다.
그러므로 이어지는 포스팅에서는 스프링 부트에 Reslience4J를 적용하는 방법에 대해 알아보도록 하자.
관련 포스팅
- 서킷 브레이커 패턴(Circuit Breaker Pattern)의 필요성 및 동작 원리
- RestTemplate에 Resilence4J 서킷 브레이커 적용하는 방법과 예시
- OpenFeign에 Resilence4J 서킷 브레이커 적용하는 방법과 예시 및 주의사항
'나의 공부방' 카테고리의 다른 글
[Post Mortem] 로블록스 장애 포스트모템(Roblox Return to Service 10/28-10/31 2021) (2) | 2023.09.12 |
---|---|
[Post Mortem] 데이터독 장애 포스트모템(2023-03-08 Incident: Infrastructure connectivity issue affecting multiple regions) (0) | 2023.09.05 |
[개발서적] 클린 아키텍처 6부 세부사항 - 내용 정리 및 요약 (2) | 2022.11.04 |
[개발서적] 클린 아키텍처 5부 아키텍처 - 내용 정리 및 요약 (4) | 2022.10.27 |
[개발서적] 클린 아키텍처 4부 컴포넌트 원칙 - 내용 정리 및 요약 (0) | 2022.10.05 |