MSA 환경에서의 장애 발생
모든 서비스 운영에서는 아무리 완벽한 설계를 했다고 해도, 예기치 못한 에러가 발생할 수 밖에 없다. 때문에 우리는 완벽한 시스템을 만들기 보다, 실패에 빠르고 유연하게 대응할 수 있는 시스템을 만드는 것에 무게를 두어야 한다. 즉, 장애가 발생해도 견딜 수 있는 내결함성(Fault Tolerance)이 더욱 중요하다는 것.
특히 MSA와 같은 분산 환경에서는 서비스가 다른 서비스를 동기 호출 시, 실패할 가능성이 항상 존재한다. 서비스가 모두 개별 프로세스로 동작하고 있기 때문에, 응답하지 못하거나 응답이 매우 늦어지는 문제가 발생할 수 있다.
예시로 서비스 A가 서비스 B를 호출하는 상황에서 서비스 B에 장애가 발생했다고 가정해보자. 이 경우,
1.
서비스 A를 호출하는 클라이언트는 항상 에러 응답을 받게 된다.
2.
서비스 A의 모든 쓰레드가 서비스 B의 응답을 받기 위해 대기하면서, 더 이상 새로운 클라이언트 요청을 받을 수 있는 쓰레드가 고갈되어 장애가 전파된다.
여기서 핵심은 서비스 B의 장애가 서비스 A까지 전파된다는 점이다.
MSA 환경은 한 번의 요청으로도 수개의 서비스를 거쳐 응답이 이루어질 수도 있다. 즉, 하나의 서비스의 장애가 연쇄적으로 이어져 전체 서비스의 장애로까지 이어질 수 있다는 점이다.
더 큰 문제는, 이런 상황에서 장애의 시작점을 파악하는 것이 쉽지 않다는 것이다. 그렇기 때문에 MSA는 스스로 회복해야하며, 장애를 격리할 수 있어야한다.
Circuit Breaker Pattern
이러한 문제를 해결하기 위해 등장한 것이 서킷 브레이커 패턴이다.
회로 차단기의 동작 원리
일반적으로 회로는 닫혀있어서 전류가 흐르게 된다. 하지만, 전구에 문제가 생겨서 전류가 계속 흐르면 과부하 등 위험한 상황이 발생한다고 치자.
그럴 때 회로 차단기는 자동으로 회로를 열고 전류를 차단하여 위험한 상황을 방지해준다. 이렇듯 문제 상황을 감지하고, 자동으로 방지해주는 기능을 수행하는 것이 회로 차단기(circuit breaker)인데, 서킷 브레이커 패턴은 이러한 회로 차단기로부터 아이디어를 얻어 만들어졌다.
서킷 브레이커의 3가지 상태
실제 회로를 기준으로 전구가 외부 API 또는 Callee에 해당하고, Power Source가 클라이언트(다른 서비스를 호출하는 서버) 또는 Caller에 해당한다. 그리고 회로 차단기에는 크게 Closed, Open, Half Open 3가지 상태가 존재한다.
1.
Closed
•
정상 상태. 모든 요청은 통과됨.
•
오류가 연속으로 발생하면 Open 상태로 전환.
2.
Open
•
외부 서비스가 불안정하다고 판단된 상태.
•
일정 시간 동안 외부 호출을 차단하고, 즉시 fallback 처리.
3.
Half Open
•
Open 상태에서 설정한 시간 이후, 일부 요청을 시도해봄.
•
다시 성공하면 Closed로 돌아가고, 실패하면 다시 Open 상태로.
여기서 외부에 장애가 발생했는지 판단하는 기준은 크게 2가지가 있는데, 각각의 정해진 임계치가 넘어갈 경우 요청이 차단된다.
•
slow call : 기준 시간보다 오래 걸린 요청
•
failure call : 실패하거나 오류를 응답받은 요청
때문에, 이러한 기준을 적용하여 다음과 같은 규칙을 만들 수 있다.
•
특정 요청이 3번 연속 실패할 경우 요청을 차단한다.
•
특정 요청이 5번 연속 n초 이상 시간초과 할 경우 요청을 차단한다.
•
차단했던 요청이 3번 연속 성공할 경우 요청을 전송한다.
동작 예시
1.
일반적으로 외부 서버는 항상 실행중이므로, 서킷이 닫혀잇고 요청이 정상적으로 전달됨
2.
외부 서버에 장애 발생
3.
요청이 계속해서 실패하고, 회로가 Open 상태가 됨
4.
이후의 요청들은 더 이상 전달되지 않고 차단되며, 빠르게 에러 또는 실패 응답을 반환함
5.
이후에 외부 서버가 정상적으로 복구됨
6.
회로가 Open 상태가 된 지 특정시간이 지나고, Half Open 상태로 변경됨
7.
일부 요청들이 외부 서버로 전달되고, 응답에 성공하여 Closed 상태로 변경됨
8.
모든 요청들이 정상적으로 전달됨
Java 진영의 서킷 브레이커 라이브러리
자바 진영의 서킷 브레이커 라이브러리는 크게 Hystrix와 Resilience4j가 존재한다. Hystrix는 Netfilx에서 만든 오픈소스인데, deprecated 되었으므로, resilience4j를 쓰면 된다.