마이크로서비스 관계 패턴 - 통신 패턴과 Event driven architecture

Updated:

마이크로서비스 관계 패턴 - 통신 패턴과 Event driven architecture

아키텍처 유형 패턴 유형 설명
마이크로서비스 외부 아키텍처 인프라 패턴 마이크로서비스를 지탱하는 하부구조 인프라를 정의하는 패턴들
  플랫폼 패턴 인프라 위에서 마이크로서비스를 운영 관리를 지원하는 플랫폼 차원의 패턴들
  마이크로서비스 통신/관계 패턴 마이크 서비스 유형 간의 관계를 정의하고 처리하는 패턴들
마이크로서비스 내부 아키텍처 마이크로서비스 내부 패턴 마이크로서비스 내부의 외부 연동, 비지니스로직,저장소 처리를 정의하는 패턴들

마이크로서비스 통신 패턴

마이크로서비스 간의 호출은 어떤 방법을 사용 할까?

동기 통신 방식

동기 호출 방식은 클라이언트에서 서버 쪽에 존재하는 마이크로서비스 REST API를 호출할 때 기본 통신 방법이 되며 다양한 클라이언트 채널 연계나 라우팅 및 로드 밸런싱을 원활하게 하기 위한 방법으로 중간에API G/W를 사용할 수 있다.

아래와 같이 웹이나 앱에서 API G/W를 통해 상품, 추천, 리뷰 마이크로서비스를 동기 호출하는 것을 볼 수 있다.

프론트엔드에서 백엔드 호출

그렇다면 이렇게 클라이언트 호출은 동기 호출 방식을 사용하는데 백엔드 마이크로서비스간의 호출은 어떠한 방법을 사용하면 될까? 즉 추천서비스가 상품서비스와 리뷰서비스를 호출한다면 API를 통해서만 호출해야 할까?

물론 제일 먼저 검토해야 할 방법은 REST API 같은 동기식 호출이다. 동기 방식은 Sync 방식이라고 하는데 동기식 호출은 요청(Request) 하면 바로 반응(Response)이 오는 방식을 말한다. 아래 그림을 보면 모바일 UI고객의 주문내역을 확인하기 위해 주문서비스에 HTTP GET 방식의 요청을 하면 주문서비스는 고객정보를 확인하기 위해 고객서비스에 GET방식의 동기 호출을 하고 있다. 그에 따라 바로 응답이 발생하고 성공 시 200이라는 OK 코드를 받아오는 것을 볼 수 있다. 이렇게 바로 요청하면 응답이 바로 오는 직관적인 방식이기 때문에 가장 많이 쓰이고 구현 하기 쉽다. 그렇지만 호출을 받은 마이크로서비스에서 장애가 생긴다면 어떨까? 호출한 서비스는 반응이 올 때까지 기다리게 되고 반응이 오지 않으면 계속 기다리면서 재호출하게 된다.

그러면 여러 개의 서비스간의 연계로 업무를 처리하는 마이크로서비스 구조에서는 장애가 연쇄적으로 발생할 수 있다. 또한 서비스가 다른 서비스를 호출하여 바로 얻은 정보를 이용해 기능을 제공한다는 의미는 그 서비스들간의 의존관계가 높다는 것을 의미한다. 이런 상태의 서비스 제공은 독자적인 마이크로서비스별로의 비즈니스 기능 처리를 어렵게 한다. 그래서 이러한 장애의 파급효과 및 의존관계를 낮추기 위한 다른 통신 방법이 필요하다.

동기 통신

비동기 통신 방식

아래 그림의 방식은 메시지 기반의 비 동기식(Asynchronous) 호출이다. 이 방식은 동기식 호출처럼 응답을 기다리지 않는다. 메시지를 보낸 다음에 응답을 기다리지 않고 자신의 일을 처리한다. 물론 보낸 결과가 어떻게 되었는지 응답을 받지 않으니 동기식처럼 완결성을 보장할 수는 없다. 따라서 이를 보장하기 위한 메커니즘이 필요한데 보통 아파치 카프카(Apache Kafka), 래빗엠큐(RabbitMQ), 액티브엠큐(ActiveMQ) 같은 메시지 브로커(Message broker) 사용한다.

이러한 메커니즘에서는 메시지를 보내는 생산자(Producer)와 메시지를 가져다가 처리하는 소비자(Consumer)가 서로 직접 접속하지 않고 메시지 브로커에 연결된다. 메시지 브로커에 전달할 메시지를 던지고 자신의 일을 처리하면 메시지 브로커가 전송을 보장하게 된다. 그런데 여러 서비스에서 던진 메시지를 처리하기 위해서는 메시지 브로커 자체에 부하가 걸릴 수가 있다. 그럴 경우 메시지 브로커는 메시지 처리 규모에 따라 확장이 가능하다.

비동기 통신

이러한 방식은 메시지가 브로커에 의해 중계되기 때문에 통신하는 서비스들이 물리적으로 동일한 시스템에 위치할 필요도 없고 서로 프로세스를 공유할 필요도 없고, 심지어 동일한 시간대에 동시에 동작하지 않아도 된다. 따라서 서비스 요구에 따라 늘어나거나 줄어들 수 있는 탄력성이 높은 클라우드 플랫폼 환경에서 서비스가 다운되었을 때 또는 시스템을 더 확장해야 할 때 사용할 수 있는 매우 효과적인 방법을 제공 해준다.

비동기 방식의 Event driven architecture

이런 비동기 통신 방식을 이용하여 느슨한 연계를 지향하는 아키텍처가 있다. 어떤 이벤트에 반응한다는 의미로 이벤트 기반 아키텍처(Event driven architecture) 라고 부르는데 이벤트 기반 아키텍처는 예전부터 사용된 키워드로 분산된 시스템 간에 발신자가 이벤트를 생성, 발행 (publish)하고 필요로 하는 수신자에게 전송하면 구독하고(Subscribe) 있던 수신자가 이벤트를 처리하는 형태의 시스템 아키텍처 이다. 여기서 이벤트라 함은 ‘상태의 변화’를 의미하며 기존 순차적 방식의 아키텍처와 달리 특정 행동이 자동으로 순서에 따라 발생하는 것이 아닌 어떤 상태의 변경에 대한 반응으로 동작 한다는 점이 상이하다.

이런 방식은 일반 실생활에서도 효율성을 위해 이미 많이 사용하는 방식이다. 아래 그림을 통해 예를 들어 보도록 하겠다. 커피숍이 있는데 손님이 주문을 하게 되면 주문접수자는 주문을 받는다. 그리고 바리스타에게 커피 제작을 의뢰하게 된다. 이때 바리스타는 하나의 주문이 바리스타에 의해 완료될 때까지 더이상 주문을 받지 않고 기다리지 않는다. 즉 주문접수>커피 제작>고객 전달의 하나의 무결, 완결된 단위로 다루지 않는다.

여러 개의 주문을 받아 꾸준히 주문 목록에 적고 동시에 커피 주문이 들어왔다는 이벤트를 바리스타에게 계속 전달한다. 그럼 바리 스타도 마찬가지로 커피 주문이벤트를 순차적으로 제작 목록에 기입하고 주문한 종류에 해당하는 커피를 만들게 된다.

그리고 커피 제작이 완료되면 커피제작완료 이벤트를 보내고 이것이 진동벨을 통해 손님에게 통보되는 것이다. 하나의 커피 주문을 받고 이것이 제작될 때까지 다른 주문 접수가 안 된다면 매우 비효율적일 것이다. 주문은 많이 들어오는데 바리스타 부족하다면 추가로 더 투입될 수도 있다. 이렇게 이런 이벤트 기반의 방식은 여러 개의 주문을 받아 여러 개의 커피를 동시에 제작할 수 있는 효율성을 만들어 준다.

이벤트 기반 아키텍처 개념도

이와 같이 이벤트 기반 아키텍처는 이벤트를 생산하는 모듈과 이벤트에 대응하는 모듈을 분리하고 상호 독립적으로 동작하게 함으로써 병렬 처리를 촉진하게 해준다. 또한 이러한 이벤트 기반 아키텍처의 전달 메커니즘으로 앞서 논한 비동기 메시지 메커니즘을 선택하면 더욱 더 효과적이다.

이런 이벤트 기반의 아키텍처와 비동기 통신 메커니즘 함께 사용하는 마이크로서비스를 이벤트 드리븐 마이크로서비스(Event Driven Microservice) 라고도 부른다. 이런 이벤트 메시지를 사용하면 발신자와 수신자를 장소와 시간에서 쉽게 분리할 수 있으며 마이크로 서비스가 추구하는 느슨한 결합으로 확장성, 탄력성에 많은 이점을 제공한다.