Programming

[MSA] #2 Microservice Architecture 란?

AlwaysPr 2018. 2. 6. 22:31

[MSA] #1 Monolithic Architecture 란?

[MSA] #2 Microservice Architecture 란?

[MSA] #3 Circuit Breaker

[MSA] #4 API Gateway

[MSA] #5 Service Discovery

[MSA] #6 Spring Cloud Netflix



이전 글에서는 Monolithic Architecture에 대해서 알아봤습니다. Monolithic은 모든 것이 하나로 묶여있다고 말했었는데요, 이번에 소개할 MSA는 묶여있는 것을 나누는 것입니다. 마틴 파울러는 MSA를 다음과 같이 정의합니다.

마이크로 서비스 아키텍처 스타일은 단일 응용 프로그램을 나누어 작은 서비스의 조합으로 구축하는 방법이다.



위의 그림은 이전에 본 Monolithic으로 구현된 프로젝트입니다. MSA로 변경하게 되면 어떻게 변할까요?



가로 방향으로 구분되어 있던 경계가 MSA에서는 세로 방향으로 구분됩니다. 이는 하나의 프로젝트가 프레젠테이션, 비즈니스, 데이터베이스 계층으로 구분되던 것을 하나의 서비스가 하나의 프로젝트로서 프레젠테이션, 비즈니스, 데이터베이스 계층을 가지게 됨을 의미합니다. 즉 각각의 서비스 별로 프로젝트가 생기게 되며, 하나의 서비스가 문제가 생긴다고 해서 다른 서비스에 영향을 주지 않습니다.


Method로 호출하면 되는 걸 왜 굳이 REST 방식으로 호출하고, 잘 돌아가는 프로젝트를 굳이 시간을 들여 나누어서 얻을 수 있는 것은 어떤 것이 있을까요?


1. 빌드 및 테스트 시간을 단축시킬 수 있다.

30개의 서비스를 가진 Monolithic 의 빌드 시간이 30분이었다면, MSA는 각각의 서비스를 1분 만에 빌드 할 수 있습니다. 이는 CI / CD를 추구하는 기업에서는 좀 더 적합한 모델이 됩니다. 왜냐하면 하루에도 몇 번을 빌드 및 배포를 해야 하는데 그때마다 많은 시간을 소모하게 된다면 낭비이기 때문입니다.


2. 폴리글랏 아키텍처 구성이 가능하다.

상황에 맞게 기술을 유연하게 적용할 수 있습니다. 예를 들어 TPS(시간당 트랜잭션)가 높고, 읽기 작업이 많은 서비스에는 Node + Redis로 구현을 하고, 트랜잭션 및 안정성이 중요한 서비스에는 Spring + RDB를 적용할 수 있습니다.


3. 탄력적이고 선택적인 확장이 가능하다.

MSA는 작은 단위의 작업이라서 필요한 서비스만을 선택적으로 확장할 수 있습니다. 만약, 주문 서비스와 이벤트 서비스의 사용률이 90 : 10 이라면 이벤트 서비스만을 선택적으로 확장(scale out) 할 수 있습니다.


4. 하나의 서비스가 다른 서비스에 영향을 주지 않습니다.

이전 글처럼 책을 무료로 주는 이벤트를 한다고 가정을 해보겠습니다. 이벤트 서비스에 트래픽이 몰려 해당 서버가 죽더라도 다른 서비스에는 영향이 가지 않습니다. 각 서버마다 서비스를 놓기 때문이죠. 

물론, 죽은 서비스를 타 서비스가 호출하게 되면 문제는 생깁니다. 이는 Circuit Breaker에서 좀 더 알아보도록 하겠습니다.








이러한 것은 각각의 서비스가 분리됨으로써 가능한 이점들입니다. 그러면 서비스를 분리함으로써 생기는 문제점은 무엇이 있을까요?


1. 성능 이슈가 있다.

Monolithic은 다른 서비스 간의 상호작용이 필요할 시에는 Method 호출을 이용합니다. 즉 이러한 행위는 메모리 안에서 일어나죠. 그러나 MSA와 같은 경우에는 주로 HTTP를 사용합니다. 이는 Network IO를 통하여 다른 서버까지 갔다 다시 와야 됨을 의미합니다. '첫 번째 문제점이 성능이라니...'라고 생각이 들 법도 하지만 요즘은 하드웨어나 기술이 많이 발전했고 성능보다는 유지 보수에 좀 더 무게중심을 둔다는 점을 미뤄볼 때, 개인적으로는 Client가 크게 체감하지 못할 정도면 MSA의 장점에 좀 더 손을 들어줘도 될 거 같습니다.


2. 트랜잭션이 불편하다.

Spring에서는 @Transactional이라는 어노테이션하나만 달아주면 자동적으로 트랜잭션 처리를 해줍니다. 그러나 서비스가 각각으로 나뉘게 되면 불편함이 따르긴 합니다. 그래서 MSA에서는 서비스 간에 Global 트랜잭션이 일어나는 상황보다는 Local 트랜잭션이 주로 이루어지게 경계를 나누고, 불가피하게 서비스 간에 트랜잭션이 필요하면 트랜잭션 로직을 추가합니다.


3. 관리 포인트가 늘어난다.

Monolithic은 간단한 경우 어플리케이션서버와 DB 서버 두 개를 관리하면 되지만, MSA에서는 기본적으로 서비스 수 * 인스턴스만큼의 서버 (경우에 따라 DB)가 존재하고 서버가 늘어난 만큼 로깅, 모니터링, 배포, 테스트, 클라우드 환경에서의 관리들은 부담스럽니다. 이러한 문제는 관리에 들어가는 비용을 줄이기 위해 자동화와 간단하게 모니터링할 수 있는 환경을 권장합니다.


spring boot admin - 모니터링

jenkins - 테스트, 빌드, 배포 자동화 (CI)




MSA의 경계의 기준은 어떻게 될까요?

  • 자율적인 기능 
  • SRP 
  • 배포 단위의 크기 
  • 서브도메인 
  • 폴리글랏 아키텍처 
  • 선택적 확장 
  • 작고 애자일한 팀 
  • 트랜잭션


서비스간의 상호작용은 어떻게 이뤄져야 할까?


주문이 일어날 때는 간략하게 유저와 책 정보를 주문 테이블에 넣고, 배송 서비스에 유저와 책에 대한 정보까지 전달을 합니다. 유저, 책은 동기적으로 일어나야겠지만 배송은 비동기적으로 일어나도 상관이 없을 것 같네요


동기 : REST/JSON

비동기 : MQ 프로토콜




MSA가 다른 Architecture과 마찬가지로 모든 상황에 적합한 것은 아닙니다. 각 기업마다 갖가지 상황이 존재할 것이고, 이를 기반으로 뭐를 내주고 뭘 얻을 것인지 이해타산을 잘 따져야 합니다. 특히 상황에 맞는 설계가 가장 중요할 것 같습니다 가령. Monolithic을 메인으로 삼고 유연성이 필요한 서비스들만을 분리하는 것도 하나의 방법이 됩니다.



참고

  • https://tkddlf59.github.io/2016/10/10/2016-10-10-msa1/
  • http://www.aladin.co.kr/shop/wproduct.aspx?ItemId=113808876