동기 / 비동기
동기
- 일반적으로 자주 사용하는 방식으로 직관적이다.
- Callee 서비스로 부터 응답이 올 때까지 기다린 뒤 후처리를 한다.
- Callee 서비스가 항상 가용한 상태여야 한다.
비동기
- Callee 서비스에 요청을 보내고 다음 작업 흐름으로 넘어간다
- Callee 서비스로부터 응답이 왔을 때 처리할 callback() 함수를 정의한다.
- Callee 서비스가 가용한 상태가 아니더라도 Caller 서비스는 동작해야 하므로 분산 환경에서 자주 사용되는 방식이다.
비동기 종류
Broadcasting
단방향 통보로 응답값을 기대하지 않고 데이터를 던지고 자신의 작업 흐름으로 돌아오는 것이다. 신경 쓸 필요 없다. 그냥 던져라
Async/Await
자신이 할 일을 하다가 Callee 서비스로부터 응답이 오면 callback() 을 통해 후처리를 한다.
polling 방식도 있으나 부하가 심해서 쓰지 않는 것을 권장한다.
Publish/Subscribe
메시지 큐에 카드를 등록하는 Publisher - Producer 와 큐에 있는 카드를 소비하는 Subscriber - Consumer 가 있다.
async/await 패턴에서는 callee가 가용한 상태가 아니면 응답 값을 확인할 수 없으므로 pending 상태가 지속되지만 메시지 큐에서는 발행자가 카드를 올려 두면 구독자가 가용한 상태일 때 소비하기 때문에 서비스 전체적 가용성이 향상된다.
분산트렌젝션
여러 서비스간 데이터의 트렌젝션 처리를 위해 메시지큐를 사용하는 MSA 구조에서 기존의 ACID 트렌젝션 구조는 더이상 통용되지 않는다.
따라서 트렌젝션을 하나로 묶는 것이 아니라 분산시켜 처리해주어야 하며 이에 따른 부작용들을 보상트렌젝션을 통해서 해결해주어야 한다.
Single Service
- DB Transaction -> ACID
- 2 Phase Commit
- Framework
하지만 분산 트렌젝션( 메시지 큐 환경 )에서는 2PhaseCommit을 거의 지원하지 않고 지원하더라도 고가용의 Connection cost, Big/Long Transaction등으로 비효율적이다.
ACID 의 방안으로 BASE 가 나왔다.
ACID
- A : Atomicity - 트렌젝션이 모두 반영되거나 모두 반영되지 않아야 함
- C : Consistency - 트렌젝션의 처리 결과가 항상 일관성이 있어야 함
- I : Isolation - 하나의 트렌젝션이 진행 중 다른 트렌젝션이 끼어들 수 없음
- D : Durability - 트렌젝션이 성공했다면 그 결과는 영구적으로 반영돼야 함
BASE
- BA : Basically Available - 가용성은 기본이다
- S : Soft State - 노드의 상태는 내부 정보에 의해 결정되는 것이 아니라 외부에서 전송된 정보에 의해 결정된다.
- E : Eventually Consistency - 실시간은 아니더라도 최종적으로는 데이터 일관성을 유지해야 한다.
보상 트렌젝션 ( Compensating Transaction )
Undo/Rollback 에 대한 대안으로 기존 트렌젝션을 무효화 하기 위한 작업이다.
항상 쌍으로 API를 열어야 한다. ( 성공 시 / 실패 시 )
보상 트렌젝션도 실패시 재 호출, 수동 호출 하는 API를 열어두고, Slack으로 알람을 보내 개발자가 직접 보상 트렌젝션을 하는 방식이 자주 사용된다고 한다.
SAGA 패턴
Orchestration
중앙 통제 하에 여러 서비스와 상호작용해 개별 트렌젝션을 하나로 묶어 관리하고 실패시 보상 처리를 하는 패턴이다.
여러 개의 SVI/Operation 을 묶어서 새로운 API를 만드는 개념이다 .
Choreography
메시지 큐를 통해 서비스들 간 이벤트를 주고 받는 방식으로, Event Driven 방식의 보상 트렌젝션이다.
각 서비스들은 메시지 카드를 소비할 때에 자신의 역할만 할 뿐 다른 서비스의 처리 로직을 알 필요가 없다.
Choreography 참가 서비스들은 Message Queue 를 이용해 서로의 이벤트를 구독하고 트렌젝션을 수행한 뒤 결과를 이벤트로 발행하는 방식이다.
장단점
Orchestration
실행 논리가 중앙에서 컨트롤하기 때문에 순환 종속성이 적어지고 테스트를 하기 쉽다.
하지만, 중앙 서비스가 하나 더 필요하고, 해당 서비스의 로직이 복잡해 질 수 있으며 이 때문에 다른 서비스들의 결합도가 강해질 수 있다.
Choreography
이벤트 방식으로 SAGA 패턴에 충실하고, 이벤트 큐 수신 시 각자의 역할에만 충실하면 되기 때문에 서비스간 결합도가 낮다.
하지만, 작업 처리가 분산돼 직관적이지 않으며 순환 종속성이 증가하고 이벤트간 추적이 어려워 디버깅이 힘들어질 수 있다.
분산 데이터 조회
서비스별로 DB가 분리돼있기 때문에 Business Intelligence 를 위해 하나의 화면에서 보기 위해 호출시 어려움이 있을 수 있다.
분산 데이터를 조회하기 위해서 존재하는 두가지 패턴이 있다.
API Composition
여러 서비스 API 호출 결과를 조합하여 응답하는 형식으로 비동기로 여러 서비스 API를 병렬 호출한 뒤 그 결과를 조합해서 조회한다.
CQRS
Command와 Query의 책임을 분리하는 패턴으로 각 서비스에 어울리는 DB를 자유롭게 선택 가능해 MSA의 polyglot 사상을 지향한다.
데이터 복제 방식의 종류로 CDC , Batch/ETL , Message Queue 가 존재한다.
- CDC : Changed Data Capture - 데이터가 변경되는 것을 감지해 필요한 후속 처리를 진행하는 방식으로 대량 자료 조회에 적합하지만 서비스에 부하가 심해 MSA 구조에서는 지양해야하는 방법이다.
- Batch/ETL : 여러 데이터 소스로부터 데이터를 추출하여 가공 후 Data Warehouse등에 적재하는 방식으로 주기적으로 대량 데이터 복제가 가능하나 복제 주기가 길어서 적시성이 높은 업무에 사용불가하다.
- Message Queue : 비동기 방식으로 데이터를 복제하기에 대용량 데이터는 어렵지만 대용량 트래픽에는 유용하게 사용되며 큐를 사용하지 않고 broadcasting을 통해서도 데이터 복제가 가능하다.
장단점
API Composition
CQRS에 비해 단순하고 이해하기 쉬워 단순한 데이터 트래픽에는 유용하다.
하지만, API Composition에 참여하는 모든 서비스가 가용 가능한 상태여야하고, 서비스별 응답 속도에 영향을 많이 받으며 네트워크 트래픽이 큰 경우에는 적합하지 않다.
CQRS
역할의 분할 ( 조회 / 트렌젝션 ) 로 모델이 단순해져 필요한 데이터가 이미 서비스에 존재해 독립적인 서비스 운용이 가능하다. 저장/조회용 서비스에 별도 기술 스택 적용이 가능해 polyglot하고, 성능의 향상을 기대할 수 있다.
하지만, 데이터 소스 분리, 메시지 큐 방식 등 서로 다른 구현 기술의 복잡성이 늘고, 디버깅의 어려움이 있으며 일시적으로 정합성이 맞지 않아 dirty write/read 가 발생할 수 있다.
'원론 > MSA' 카테고리의 다른 글
API First Design (0) | 2025.01.26 |
---|---|
MSA 서비스 분리 (0) | 2025.01.26 |
MSA 모델링 (1) | 2025.01.26 |
MSA 개요 (0) | 2025.01.11 |