Self-contained service pattern (feat. Decomposition)
안녕하세요. yeTi입니다.
오늘은 MSA 의 거장, Chris Richardson 이 운영하는 Microservice Architecture 에서 제공하는 패턴 중 하나인 Self-contained service
패턴의 번역본을 생성하고자 합니다.
** 본 컨텐츠의 원본은 Chris Richardson 의 저작물인점을 참고해주세요. **
Context
온라인 음식 배달 애플리케이션인 FTGO 애플리케이션을 예로 들어보겠습니다. 애플리케이션의 클라이언트는 HTTP POST /orders
요청을 통해 주문을 생성하고 600ms 이내의 응답을 기대합니다. FTGO 애플리케이션은 마이크로서비스 아키텍처를 사용하기 때문에 주문 생성을 구현하는 책임이 여러 서비스에 흩어져 있습니다. POST
요청은 먼저 주문 서비스
로 라우팅되며, 이 서비스는 다음 서비스들과 협업해야 합니다:
레스토랑 서비스
- 레스토랑의 메뉴와 가격을 알고 있습니다.소비자 서비스
- 주문한소비자
의 상태를 파악합니다.주방 서비스
- 요리사에게 무엇을 요리할지 알려주는티켓
을 생성합니다.회계 서비스
-소비자의 신용 카드를 승인합니다.
주문 서비스
는 동기식 요청/응답을 사용하여 이러한 각 서비스를 호출할 수 있습니다. 예를 들어 REST 또는 gRPC를 사용하여 서비스 간 통신을 구현할 수 있습니다.
그러나 동기식 요청/응답을 사용할 때의 주요 단점은 가용성을 감소시킨다는 것입니다. 주문 서비스
의 공동 작업자 중 한 명이라도 사용할 수 없는 경우 주문을 생성할 수 없고 클라이언트에 오류를 반환해야 하기 때문입니다.
다른 접근 방식은 CQRS 및 사가 패턴을 사용하여 주문 서비스
와 공동 작업자 간의 모든 동기 통신을 제거하는 것입니다. 주문 서비스
는 레스토랑 서비스
에서 데이터를 동기적으로 가져올 필요가 없도록 CQRS 패턴을 사용하여 레스토랑 메뉴의 복제본을 유지할 수 있습니다. 그리고 사가 패턴을 사용하여 비동기적으로 주문의 유효성을 검사할 수 있습니다. 주문 서비스
는 보류
상태의 주문
을 생성하고 POST /order
에 응답을 보냅니다. 이후 다른 서비스들과 비동기 통신을 통해 주문 생성을 완료합니다.
이 접근 방식의 주요 이점은 가용성을 향상시킨다는 것입니다. 주문 서비스
는 다른 서비스 중 하나를 사용할 수 없는 경우에도 항상 POST /orders
요청에 응답합니다. 그러나 사가를 사용하여 주문 생성을 완료하는 한 가지 단점은 POST
에 대한 응답이 주문이 승인되었는지 여부를 클라이언트에게 알려주지 않는다는 것입니다. 클라이언트는 주기적으로 GET /orders/{orderId}
를 호출하여 확인해야 합니다.
Problem
동기 요청을 처리할 때 서비스가 다른 서비스와 어떻게 협업해야 하나요?
Forces
- 마이크로서비스 아키텍처는 요청을 처리하는 책임을 여러 서비스에 분산하는 경우가 많습니다.
- 일반적으로 작업은 응답 시간이 짧고 가용성이 높아야 합니다.
- 작업의 가용성은 요청을 처리하는 동안 호출되는 서비스의 가용성의 곱입니다: serviceAvailabilitynumberOfSynchronouslyCollaboratingServices
- 서비스는 실패한 공동 작업자에게 요청을 다시 시도할 수 있지만 응답 시간이 늘어납니다.
Solution
다른 서비스의 응답을 기다리지 않고 동기 요청에 응답할 수 있도록 서비스를 설계하세요.
서비스를 독립적으로 만드는 한 가지 방법은 필요한 기능을 별도의 서비스가 아닌 서비스 모듈로 구현하는 것입니다. 예를 들어 주문 서비스
와 레스토랑 서비스
를 병합할 수 있습니다.
서비스를 독립적으로 만드는 또 다른 방법은 CQRS 및 사가 패턴을 사용하여 다른 서비스와 협업하는 것입니다. 독립형 서비스는 사가 패턴을 사용하여 비동기적으로 데이터 일관성을 유지합니다. 다른 서비스에서 소유한 데이터의 복제본을 유지하기 위해 CQRS 패턴을 사용합니다.
Example
앞서 설명한 FTGO 애플리케이션의 주문 서비스
는 독립형 서비스의 예입니다. 예를 들어, createOrder()
작업은 Restaurant Service
가 소유한 데이터의 CQRS 복제본을 쿼리하여 주문의 유효성을 검사하고 가격을 책정한 다음 사가를 시작하여 주문 생성을 완료합니다.
Resulting Context
이 패턴에는 다음과 같은 이점이 있습니다:
- 가용성 및 응답 시간 개선
이 패턴에는 다음과 같은 단점이 있습니다:
- CQRS 사용 시 비용 및 복잡성 증가
- 사가 사용의 복잡성 증가
- 사가 사용 시 덜 직관적인 API
- 별도의 서비스가 아닌 서비스에서 구현되는 기능으로 인해 서비스 규모가 커짐
Related patterns
- 마이크로서비스 아키텍처 - 이 패턴의 필요성을 창출합니다.
- 사가 - 데이터 일관성을 비동기적으로 유지하기 위해 자체적으로 포함된 서비스에서 사용됩니다.
- CQRS - 다른 서비스가 소유한 데이터의 복제본을 유지하기 위해 자체 포함된 서비스에서 사용합니다.