MSA
- 설명 : 애플리케이션을 독립적으로 배포가능한 여러개의 작은 서비스로 나누어서 아키텍쳐를 구성하는 것을 얘기.
- 이 때 서비스란, 독립적으로 배포가능한 컴포넌트를 얘기하며, 별도의 서버로 존재하고, 프로토콜로 통신하며 서비스를 사용가능.
- 컴포넌트는 독립적으로 교체 및 업그레이드가 가능한 소프트웨어 단위
- 컴포넌트에는 라이브러리와 서비스가 있는데
- 라이브러리는 자신의 애플리케이션에 라이브러리 메소드만 연결되서 메모리에 있는 함수 호출을 통해 라이브러리를 사용한다
- 서비스는 애플리케이션 밖에서 웹 서비스 요청과 같은 프로토콜을 통해 통신한다
특징 1. 서비스를 통한 컴포넌트화 : MSA는 여러 개의 서비스로 분해.
- MSA는 여러 개의 서비스로 분해.
- 서비스는 애플리케이션 밖에 별도의 서버에서 웹 서비스 요청과 같은 프로토콜을 통해 통신하며 독립적 배포가 가능
- 서비스를 사용하는 이유는 독립적으로 존재해서 독립적 배포가 가능하기 때문이다
특징 2. 비즈니스 기능을 중심으로 팀이 나뉘고, 그에 따라 서비스도 나뉜다.
-
비즈니스 기능을 중심으로 팀이 나뉘고, 그에 따라 서비스도 나뉜다.
-
콘웨이의 법칙 : 조직 구조가 소프트웨어 구조에 영향을 준다
- 프론트 → DB → 백엔드 vs 주문팀이 제품 하나 알아서 다 맡음
-
독자적 배포 뿐 아니라 독자적 으로 제품 관리가 가능
특징 3. 프로젝트가 아닌 프로덕트
- 제품을 다룰 때 하나의 프로젝트로서 보는 것이아니라 제품에 대해 주인의식을 가지고 전적인 책임 가져서 제품의 전체 수명동안 제품을 관리한다
특징 4. 독립적인 데이터 관리
-
MSA는 각 서비스가 자체 데이터베이스를 관리하는 것을 선호
-
Polyglot Persistence : 같은 DB를 여러개의 인스턴스로 두거나, 여러개의 DB를 씀
-
장점 : 독자적인 관리
-
단점
- 여러 개의 서비스가 동일한 데이터를 업데이트 중일 때 데이터 일관성을 유지할 수 가 없다
- → 해결책으로 나온 것이 최종 일관성 Eventual Consistency이다
MSA 장단점
- 장점 :
- 모놀리딕이 아니라서 전체 장애를 막고, 장애를 격리할 수 있다
- 각 서비스를 다른 프로그래밍 언어로 작성 가능. 다른 Data Storage 기술을 쓰는 것도 가능
- 단점 :
Polyglot Persistence
- 설명 : 서비스가 독립적으로 DB를 가지는 것.
- 장점
- 단점
- DB를 독립적으로 나눈다는 것이 어렵다
- 데이터가 분산되어 있기 때문에 관리 어렵다
- 각자 사용하는 DBMS가 다르다
- 여러 서비스에서 동일 데이터를 접근할 때의 데이터 일관성 문제
모놀리딕 , MSA
- 모놀리딕 애플리케이션은 단일 프로세스에서 모든 기능을 만든 앱
- MSA는 독립적으로 배포가능한 여러 개의 작은 서비스들을 통해 기능을 구현한 앱
- 차이점
- 모놀리딕 앱은 단일 프로세스에서 기능을 하는 앱이기 때문에 메소드 호출을 통해 통신
- MSA는 서비스간 프로토콜을 사용해서 통신
- 모놀리딕 앱은 작은 부분을 변경할 시 전체 앱을 다시 빌드하고 배포해야 한다
하면 안되는 Entity Service Anti Pattern
서비스를 나누는 기준이 엔티티인경우
예를 들어 상품, 장바구니, 주문,주문 아이템별로 서비스를 나누었을 때
“주문하기”를 하게 되면 위 4가지 서비스가 서로 결합되어 독립적으로 관리가 불가능하다. 그래서 서비스를 나누는 기준을 엔티티가 아닌 비즈니스 기능에 따라서 나누어야한다
MSA 패턴 : Transactional Outbox Pattern
서비스는 보통 DB를 업데이트하는 트랜잭션에서 메시지 발행까지 한다.
주문 서비스 (DB에 주문 업데이트 , 사장님에게 주문 알람 발행)가 있을 때,
DB 업데이트와 메시지 전송을 한 트랜잭션으로 묶지 않으면, DB 업데이트 후 메시지는 아직 전송되지 않은 상태에서 서비스가 중단될 수 있기 때문에 문제가 됩니다.
이 두작업은 함께 원자적으로 수행되어야한다.
애플리케이션에서 메시지를 확실하게 발행하려면 어떻게 해야할까?
RDBMS 기반의 애플리케이션이라면 DB 테이블을 임시 메시지 큐로 사용하는 트랜잭셔널 아웃 박스 패턴이 가장 알기 쉬운 방법.
- 목적 : 일관성을 유지하기 위해 트랜잭션과 메시징을 하나로 다뤄야 한다
- 동작 방식 :
- 서비스에서 메시지 브로커에 바로 메시지를 발행하지 않고, outbox라는 임시 데이터베이스 테이블에 메시지를 저장한다. (ex) 데이터 생성했다는 메시지, 데이터 수정했습니다 메시지, 데이터 삭제했습니다 메시지)
- 그리고 저장된 메시지는 서비스와는 별개로 메시지 릴레이(relay, 중계기)가 outbox 테이블에 메시지를 읽어서 메시지 브로커로 발행을 한다
- outbox 테이블은 같은 데이터베이스에 위치하고 있기 때문에 데이터베이스 트랜잭션으로 다룰 수 있다. 따라서 메시지 발행에 시차가 좀 생기겠지만 “eventual consitency”를 유지할 수 있다
메시지 브로커
- 메시지 브로커 : 서비스간 통신, 중개 역할 하는 인프라 서비스
- ex) RabbitMQ, Kafka
- 장점
- 느슨한 결합 : 클라이언트는 적절한 채널에 그냥 메세지 보내는 식으로 요청. 클라이언트는 서비스 인스턴스를 몰라도 됨.
- 메시지 버퍼링 : 메시지 브로커는 처리 가능한 시점까지 메시지를 버퍼링한다. 컨슈머가 처리할 수 있을 때까지 그냥 큐에 메시지가 쌓인다.
- 단점
- 성능 병목 : 메시지 브로커 자체가 성능 병목점이 될 수 있다. 확장하도록 설계를 해야한다.
- 단일 장애점 : 가용성이 높아야 한다.
합격하소서 서비스 분해 고민점
여러 서비스에 걸쳐 데이터 일관성 유지가 되야함. 여러 서비스가 DB를 공유할 경우 일관성 문제가 발생할 수 있다.
예를 들어
Resume 자기소개서 서비스와 Recruit 채용 서비스의 경우
position이라는 데이터가 서로 필요하다.
가령 recruit 서비스에서 position 데이터를 수정하는 중에 resume 자기소개서 서비스에서 해당 position을 건들지 않도록 트랜잭션을 건다. 두 서비스간에 기능은 원자적으로 수행되어야 한다.
-> DB단에서 격리 레벨 설정
MSA vs Monolithic 을 선택하는 기준이 있습니까?
참고 문헌
마틴파울러 블로그
책 마이크로서비스 패턴