dev-writeup-2024 / march

개발 1일 1글 스터디
2 stars 0 forks source link

[03-13] circuit breaker pattern #31

Open steammando opened 6 months ago

steammando commented 6 months ago

안녕하세요? 오늘은 MSA를 하다보면 필수로 필요한, 카카오톡에도 적용되어있는 패턴인 써킷 브레이커 패턴에 대해서 살펴보도록 하겠습니다.


Micro Service Architecture를 사용하면 호출한 다른 서비스에 장애가 발생하면 연관된 다른 서비스까지 모두 장애가 생긴다. 왜냐하면 장애난 지 모르고 요청 계속 보내다가 메세지큐에 쌓이면 장애 복구할 때 그거 비우고..request timeout 날 때까지 DB풀이나 thread 계속 선점하고 있으면 메모리 터지고 다른 서비스로 장애 전파되고...그거 정상서비스로 회선 돌리고...으😫

그렇기 때문에 장애가 발생한 서비스를 탐지하고 요청을 보내지 않도록 차단하기 위해 만들어진 것이 써킷 브레이커 패턴이다.

이 패턴은 클라이언트쪽에서 장애를 방지하기 위한 것으로 실패할 수 있는 request를 계속 시도하지 않도록 한다.


이 패턴의 동작원리는 회로 차단기와 동일하다.

image

회로의 상태에 따라 동작 여부를 정한다.

정상상태 : close
오류상태 : open
반열림상태 : half open

close, open은 명확하고 half open은 open 상태가 되고 일정 시간이 지난 상황에 사용한다. 일부 허용된 요청이 성공하면 close 상태로 변경, 실패면 open으로 바로 변경한다.

그러면 무슨 기준으로 close, open처리를 진행할까

open 처리 후 일정 시간이 지나면 half open 상태로 변경된다. 다시 요청이 성공하면 close 상태로 변경되는 방식이다.

이 pattern을 사용하면 장애서비스로의 부하가 감소하고 장애 감지가 빨라진다.


이러한 circuit breaker pattern은 remote shared memory server를 사용해서 구현할 수 있다. state server 개념과 비슷한데, sliding window, error rate calculation, statue value를 관리한다.

이 방식으로 구현하면 폴링 방식으로 매번 상태값을 확인해야하지만 어느 정도 규모의 클라우드 인프라를 사용한다면 충분히 수용가능하다.

결국 이 패턴은 half open 상태가 되었을 때 open/close 여부를 결정하는 것이 포인트인데, 여러 서비스를 가동하는 msa의 경우, 서비스 별로 dependency가 있거나 특정 조건을 만족해야하는 등 모든 서비스가 합의를 해야하기 떄문에 barrier synchronization 기반으로 의사결정을 할 필요가 있다.

그래서 python을 사용한다면 @decorator 를 사용해서 기존 함수를 수정하지 않고 circuit breaker를 적용할 수 있다.

from src.circuit_breaker import circuit
...
@circuit(expected_exception=Exception, name="kakao")
def post(self, request, *args, **kwargs):
    pass

회사의 장애 복구 매뉴얼을 보다가 생각나서 작성하게 되었다. 어떤 책에 나왔던 패턴인데 꽤 많은 곳에서 적용되있는 것으로 알고 있다. 특히 외부 API를 사용한다면 더욱더