MSA(Micro Service Architecture)

TAS
13 min readJul 12, 2022

--

아키텍처를 공부할 때는 시간을 효율적으로 쓰기위해서 이동중에 IPad로 정리하면서 공부를 했는데, key note에 저장된 내용들을 이직을 준비하면서 정리한다. 주요 메이저 서비스 회사들은 MSA로 전환을 했고, 필요에 의해 진행중이거나 시작하는 회사들이 많아서 이걸 이해하고 있는지 꼭 물어보는 듯하다. 이참에 정리한 결과물을 다시 정리하면서 익힌다. 고강해지자.

자료의 출처는 아래와 같다.

그림으로 보는 IT인프라 구조
대용량 아키텍처와 성능 튜닝(조대협)
가트너 마이크로 서비스 아키텍처 예시

그리고 그냥 MSA에 대한 정보만 필요하다면 아래 ‘MSA에 대하여’라는 소제목으로 이동한다.

분산 시스템

HW 발전과 SW 발전의 역사를 나란히 두고 보면 HW의 비약적 발전 이후에는 SW가 비약적으로 발전하는 패턴을 확인할 수 있다. 정확히 재단하기는 어렵겠지만 정확이 2000년대 초반을 기점으로 폭발적으로 성장했다. 그리고 2010년대 부터는 증가한 트래픽을 처리함에 부하를 분산하는 구조로 시스템을 나눠 설계하는 경향이 짙어지고 그에 따른 오픈소스들도 등장하는 것으로 보인다.

아키텍처 관점에서 변화는 기존 모놀리딕 아키텍처에서 서비스 지향 아키텍처 그리고 최근에는 마이크로 서비스 아키텍처가 등장하고 있다. 인터넷에 공개 되어 있는 자료들을 바탕으로 어떻게 분산의 원칙을 파악해보았다.

당연한 이야기지만, 서비스 단위로 MECE(Mutually Exclusive Collectively Exhaustive)하게 분리를 시킨다. ( 100% 그렇다는 건 아니고 전체를 관점으로 그러하다는 것이다. 서로 겹치는 것 없이 쪼개져야하고, 쪼개진 하나하나가 모이면 전체를 포괄한다는 이론은 기술적으로 불가능하다고 생각한다.)

그림으로 보는 IT인프라 구조에 내가 정리하면서 편집한 것들

일반적으로 인프라를 위의 도식처럼 구분한다고 한다. 수직과 수평으로 분할을 할 때 수직적 분할이란 서로 다른 일(처리)를 나눈다는 관점이다. 수평이적 분할은 같은 일을 처리하는데 그 과정에서 역할을 분담한다는 관점이다.

그리고 분산과 집중은 보통 반복되는 경향을 가지고 있으며 서비스에 따라 그 패턴이 다르다고 한다.

MSA를 찾아가는 여정

책에서 본 내용과 인터넷을 찾아가면서 ebay의 아키텍처를 한번 그려보자는 심산으로 그려보았다. 그냥 공부한 것들 다 적어보았다. MSA를 목적하고 그리지는 않았고, 도서에서 제시하는 아키텍처들을 맞춰서 그려보았다.

  • AWS를 기준으로 그렸는데, Kubernetes를 적용하면 어떻게 구분될지도 표시를 추가해보았다.
  • 또한 EC2 내부의 도식은 쿠버네티스에서 Pod를 띄운다면 컨테이너화 입장에서 나타나는 계층도 표시해 보았다.
출처는 제가 그린 겁니다. 막 가져다 쓰는대신 피드백 좀 주세요.

작성 이유를 간단하게 작성해본다.

클라이언트의 요청이 있으면 먼저 로드밸런서가 부하를 분산해준다고 생각했다. 그리고 웹사이트, 모바일 등 접속의 형태를 기준으로 Api GateWay를 나눠서 사용한다고 생각했다. 서비스를 사용하게 되면 보여지는 front 부터 차이가 나고 그 구성에 따라서 back단에서 서비스를 매핑시켜주는 로직도 차이가 있다고 생각했다.

그 매핑의 역할을 메시지 큐가 한다고 생각했다. 요청을 구분해서 MQ에 넣은 다음 메시지를 소비하는 주체가 각각의 서비스가 되고, 서비스간 필요한 동기화도 MQ를 통해서 통신을 하면 되겠다고 생각했다.

그리고 대게 운영과 관련된 정책이나 데이터의 형태에 따라서 하나 혹은 그 이상을 쓴다고 생각했다.

이런 과정을 거치고나니 이건 엄격하게 MSA 아키텍처는 아니었다. 왜?

출처는 제가 그린 겁니다. 막 가져다 쓰는대신 피드백 좀 주세요.
가트너

가트너에서 예시자료로 제공하는 것과 상당한 차이가 있었다. 먼저 메시지 큐를 처리해서 사용하는 부분이 있는데, 메시지 큐가 버퍼 역할을 해서 병렬 처리를 하게해 주지만, 여전히 모든 부하가 걸릴 수 있는 지점이 발생한다. 이렇게 되면 MSA의 서비스별 부하분산이라는 기본 이념(?)에 위배가 된다.

그리고 API GateWay의 위치도 틀렸다. API GateWay는 쉽게 말하면 내부와 외부를 분리하는 것이다. 외부에 대한 부하는 API GateWay에서 끝이 나야한다. API GateWay를 통해 유입된 트래픽은 서비스 라우터에 의해서 목적지를 정하고 로드밸런서 등을 통해 부하를 분산하여 각각의 서비스로 전달 된다.

완벽하지는 않지만 일단 그리면서 쫓아온 MSA는 여기까지다.

출처는 제가 그린 겁니다. 막 가져다 쓰는대신 피드백 좀 주세요.

MSA에 대해서

위 과정을 한사이클 따라가면서 명확해 지는 느낌이다. MSA의 정의는 아래와 같다. ( 출처 : https://microservices.io/ )

Microservices — also known as the microservice architecture — is an architectural style that structures an application as a collection of services that are

- Highly maintainable and testable

- Loosely coupled

- Independently deployable

- Organized around business capabilities

- Owned by a small team

The microservice architecture enables the rapid, frequent and reliable delivery of large, complex applications. It also enables an organization to evolve its technology stack.

https://microservices.io

각각의 서비스를 조각들을 묶어서 전체 아키텍처를 구성하는 방식인 것이다. 위 그림보다는 실제 운영하는 관점에서 아래 그림이 현실적인 듯하다.

나누어진 서비스를 하나의 아키텍처로 통합하는 과정에서는 아래의 당면한 과제들이 있었을 것이다.

  1. 구축 이슈 : 서비스간 종속성에 대한 이슈 등
  2. 테스트 이슈 : 통합테스트의 어려움, 복잡도가 그만큼 증가하므로
  3. 배포 : 자동화에 대한 이슈 등
  4. 모니터링 및 디버깅 : 분산 된 서비스를 어떻게 중앙에서 관리 할 것인가?
  5. 연결성 : 부하를 어떻게 잘 분산하도록 연결할 것인가?, 서비스간의 트랜잭션 처리
  6. 운영 : 서비스별로 다른 기술 사용 등에 따라서 시스템 증가에 따른 다양한 기술이 필요해짐

이런 과제들을 해결하는 과정에서 가트너에서 제시한 이런 예시가 나온 것이라고 생각한다. 각 구성별로 왜 이런 구성이 되었는지 그리고 각 요소가 왜 있는것인지 정리해 본다.

  1. API GateWay

서비스들을 모아서 하나의 아키텍처를 만들었다. 그렇다면 상품,배송,주문,결제 이런 서비스들은 각각의 Url을 엔드 포인트로 전달 해야될까? 그렇게 된다면 아마도 사용자 입장에서는 전체 서비스를 이용하는 과정에서 여러 엔드포인트를 거쳐야 할 것이며, 서비스를 제공하는 입장에서도 네트워크 설정을 개별로 해주어야 될 것이다. 이렇게 되면 특정 서비스에 부하가 몰릴 수 있다.

그래서 가트너의 예시를 보면 API Gateway를 통해서 유입이 된 다음, 서비스 라우터에서 분산해주는 구조임을 알 수 있다. API GateWay는 일종의 버스 역할을 하는 것이며 이런 구성을 Hub&Spoke 방식이라고 한다. 이렇게 되면 외부와 내부 영역을 구분하면서 유입을 단순화 할 수 있는 이점이 있다.

가트너 마이크로 서비스 아키텍처 예시

그래서 조대협의 저서에서는 API Gateway자체에 대한 높은 수준의 기술적인 이해가 필요하다고 하는 것 같다. 실제로 넷플릭스 사례를 제시하면서, 넷플릭스에서는 여러개의 서비스를 게이트웨이 계층을 통해서 오케스트레이션(오픈 api의 매시업과 같은 개념으로 여러 개의 서비스를 묶어서 하나의 새로운 서비스를 만드는 개념)하는 모델을 사용한다고 한다.

그리고 API Gateway에서 인증이나 로깅과 같은 공통기능에 대한 중복 개발을 줄이고자 Polocy Management나 인증을 진행한다.

2. Service Router와 Load Balancing

API Gateway를 타고 들어면 Service Router에 의해 해당 트래픽이 어느 서비스로 전달 될 지 결정이 된다. 도식에서 보면 Service Discovery라고 되어있다. Discovery라는 개념은 API Gateway가 호출할(연결 될) 서비스를 찾는 매커니즘이다. java 기반의 넷플릭스 Zuul 같은 것을 예시로 들 수 있겠다.

Load Balacing은 내용이 조금 명확하지 않아서 AWS의 자료를 참고했다. AWS에서는 3가지를 제공한다고 한다.

  • Application LB
  • Network LB
  • Classic LB

로드 밸런서는 부하를 분산하는 역할이다.

3. Service

위 도식에서 Router에 구분 된 요청들이 각각의 서비스로 유입 될 것이다. 실제 서비스로 들어가는 트래픽들은 위 도식처럼 일방향으로 간단하게 처리되지 않는다.

위 도식대로만 된다고하면 각각의 ‘서비스간 통신은?’ 이런 의문이 들지 않을까?

그렇기 때문에 서비스 매시(Service Mesh) 개념이 도입된다. 서비스 간의 통신을 제어하고 표시하고 관리 할 수 있도록 하는 마이크로 서비스에 특화 된 인프라 계층이다. 서비스 메시에서의 호출은 자체 인프라 계층의 proxy를 통해서 이루어 진다.

이 proxy는 서비스 내부에 존재하는 것이 아닌 각 서비스와 함께 실행되는데 sidecar 패턴의 구현체이다. 이렇게 구성하는 이유는 서비스간 통신을 하면서 발생하는 복잡성과 특정 서비스 간 통신 과정에서 발생하는 SPOF를 손쉽게 찾을 수 있다는 이점이 있다.

실제 서비스 메시는 아래 구조로 동작한다. 각각의 서비스와 동시에 실행되는 프록를 통해서 서비스간 통신이 가능하다. 그리고 각 프록시들도 설정이 필요할텐데 트래픽을 제어하는 정책 및 구성에 따라 그 역할을 해주는 컨트롤러가 있다. 주로 많이 사용하는 도구는 Envoy Proxy를 쓴다고 한다.

출처는 제가 그린 겁니다. 막 가져다 쓰는대신 피드백 좀 주세요.

그리고 이 Service Mesh 자체를 서비스로 제공하는 Istio 같은 서비스도 있다.

4. 데이터 베이스

마이크로 서비스 아키텍처의 경우 서비스가 API에서부터 데이터베이스까지 분리되는 수직적 분할 원칙에 따라서 독립된 데이터 베이스를 가진다.

5. 모니터링

서비스는 분할되어 있지만 모니터링과 관리는 중앙집중 형태가 유리한 점이 많다. 서비스 외부에서 중앙화 된 텔레메트리를 도입해서 관리하는데 사용하는 도구로는 Grafana나 Tanos 같은 부분들이 있다.

MSA 장단점

장점

  • 서비스 단위로 출시가 되므로 빠르고 독립적인 개발이 가능하다.
  • 고가용성이 보장되는 시스템을 운영할 수 있다. SPOF로 전체가 다운되지 않는다.
  • 높은 확장성과 재사용성을 가질 수 있다.
  • 서비스별로 다른 언어로 개발이 가능하기에 협업의 범위가 넓어진다.

단점

  • 성능 이슈 : 네트워크 복잡도 증가로 지연, 패킷손실 등이 가능성이 높다. 그리고 API 통신 과정에서 마샬링 오버헤드가 발생한다고 한다.
  • 리소스(메모리) : 독립된 서비스(수직적 분할 원칙)에 따른 중복이 발생한다.
  • 테스트 : 복잡도가 증가한다.
  • 운영 : 서비스별로 사용기술 스택이 증가한다.
  • 마이크로 서비스간 트랜잭션 처리의 이슈가 생긴다.

단점에 대한 대안

  • 리소스 관리 : 리소스 관리의 효율적인 방안이 컨테이너 기반의 운영(docker)과 그 컨테이너들을 오케스트레이션 할 수 있는 kubernetes와 같은 도구입니다. 사실상 업계 표준으로 자리잡고 있습니다. 오토스케일링 등을 통해서 효율적인 관리가 가능함
  • 사용 기술스택의 증가 : 장점이자 단점인데, 이를 극복하기 위해 데브옵스라는 문화가 탄생했다. 개발과 운영을 함께하는 형태로 애자일 방식이 확산되면서 더욱 가속되고 있다.
  • 트랜잭션 이슈는 너무나 중요하므로 아래에 별도 기술

트랜잭션 이슈

어느 자료나 예시를 보아도 트랜잭션 단골 이슈는 은행인듯하다. (자본주의란..).

트랜잭션이란 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위이다. 트랜잭션은 원자성, 일관성, 독립성, 영속성이라는 특성을 지켜야 한다. 그래서 트랜잭션 연산과정에서 실패를 하게되면 롤백을 통해서 반영하지 않게된다.

기존 모놀리딕 서비스에서는 하나의 DB에서 RelationShip이 있어 하나의 서비스에서 트랜잭션을 관리하여 위 특성을 유지할 수 있다.

하지만 마이크로 서비스는 수직적 분할 원칙에 따라 각 서비스별로 데이터 베이스를 별개로 둔다. 이럴 경우 하나로 관리되던 데이터베이스가 여러개로 나뉘면서 전체 서비스에 대한 트랜잭션들이 분할되고 특정 서비스에서만 실패가 발생할 경우 처리를 어떻게 해야될지 문제가 된다.

트랜잭션 처리를 위한 방안들

Two Phase Commit와 SAGA 패턴이 대표적인 듯하다.

Two Phase Commit

방식은 Transaction Coordinator을 생성하여 전체 트랜잭션을 관리한다.

주문이 들어오고 각 서비스로 요청한다. 모두가 완료가 되면 커밋을 한다.

만약 특정 서비스에서 실패가 발생하면 모든 서비스로 롤백을 요청한다.

이 방식은 NoSQL은 지원되지 않고, Transaction Coordinator 에서 교착상태가 발생 할 수 있다.

SAGA 패턴

별도의 주문이라는 서비스에 대해서 saga orchestrator를 생성하고 각각의 서비스로 메시지를 던진다. 각 서비스들의 처리에 대한 응답이 정상적으로 완료가 되면 트랜잭션을 종료한다.

반면 어느 한 과정에서 실패가 발생하면, Orchestrator는 롤백을 시작하고 파란색라인 결제 채널로 결제취소(환불) 명령을 보내고 주문서비스의 상태를 실패를 만듦으로서 트랜잭션의 원자성을 보장한다.

장점

  • 트랜잭션을 Orchestrator를 통해 관리하므로 구현의 복잡도가 적음
  • 테스트 용이함

단점

  • Orchestrator와 MessageBroker를 추가해야 함. 인프라 구성의 변화.
  • 서비스를 분리하였는데, 일정 부분이지만 다시 결합을 하게되면서 시스템 부하 발생
  • 운영 정책에 따라서 Orchestrator의 운영로직이 복잡해질 수 있음

내용이 방대하여 빠지거나 생략된 부분은 다른 글로 보강을 하고자 한다. MSA가 자체 서비스를 가진 회사들에서 많이 사용하면서 대세가 된 부분이 있긴하지만, 아직 이정도 규모가 되지 못해서 Monolithic이나 SOA를 채택하는 서비스도 많다. 아키텍처는 주어진 상황에 적절하게 사용하면 되지만 반드시 MSA 전환 경험을 해보고 싶다.

--

--