1.마이크로서비스 설계 원칙
2.마이크로서비스 데이터 설계
3.마이크로서비스 통신 설계
4.마이크로서비스 외부 API 통합 패턴
도메인 기반 설계를 통해 더욱 안정된 서비스를 구축하고 다양한 사용자 인터페이스에 대해 보다 쉽게 각 서비스들을 재결합 할 수 있다.
많은 수의 마이크로서비스의 복잡성을 관리하려면 자동화가 필수적이다.
서비스가 독립적으로 변경되고 진화할 수 있도록 각 서비스의 구현 세부 정보를 숨겨야 한다. 필요한 정보는 DB에 직접 접근하는 것이 아닌 각 서비스 API를 통해서 얻어야 한다.
각 서비스는 자체 결정을 내릴 수 있어야 하며 그 안에서 완전한 자율성을 가질 수 있어야 한다.
Service Ochestration
: 중앙 집중식 접근 방식
Service Choreography
: 느슨하게 결합된 접근 방식
서비스 구성 요소를 변경하는 경우 다른 구성 요소를 변경하지 않고 프로덕션으로 릴리스할 수 있어야 한다.
당신의 서비스가 호출되기 위해 존재한다는 생각을 가지고 있어야 한다. 따라서 소비자 관점에서 디자인을 하고 API Docs 도구를 사용하여 API를 문서화하는 것은 필수적이다.
기본적으로 마이크로서비스는 신뢰할 수 없다는 것을 전제로 설계해야 한다. 계단식 오류를 방지하기 위해 각 오류를 격리함으로써 시스템 복원력을 높이는 것이 중요하다.
일부 서비스 호출의 실패가 전체 서비스 자원을 고갈시켜서는 안된다.
✅ Hystrix: 대표적인 오류 격리 서비스
1. 지정한 오류율을 초과한 경우 발생
2. 회로의 상태를 CLOSE -> OPEN 변경
3. 회로가 열린 상태에서 모든 요청에 대해 fallback method(대체함수) 실행
4. 지정 시간이 지난 후 HALF OPEN(하나의 요청만 원래 method로 실행) 수행
5. HALP OPEN이 성공하면 회로 상태 CLOSE, 실패하면 다시 OPEN
시스템에서 무슨일이 일어나고 있는지 알기 위해서 충분한 입력과 로그가 생성되어야 한다. 또한 보다 높은 수준의 모니터링을 위해서 상태 체크, 중앙 집중식 로그 및 통계 집계, 상관 관계 ID를 사용한 분산 추적 등이 가능해야 한다.
각 서비스 간 느슨한 결합으로 의존성을 낮추고 서비스 특성에 맞는 데이터베이스를 자유롭게 선택 가능하다.
이벤트 소싱이란, 이벤트를 위주로 비즈니스 로직을 구현하고, 애그리거트를 event store에 저장하는 것을 의미한다.
✅ 애그리거트: DDD에 기반한 설계에서 하나의 도메인에서 필요한 객체들을 하나의 군집으로 묶은 것
데이터를 가진 서비스가 직접 데이터를 조작하게 하지 않고, 서비스는 이벤트를 발생시키고 해당 이벤트는 event store에 저장만 한다.
그리고 이벤트 컨슈머가 해당 이벤트를 처리하도록 한다.
이벤트 소싱은 클라우드 환경에서의 메시지 중심의 분산 시스템에 적합하다.
이벤트 소싱은 쓰기에 적합하지만 읽기에 매우 비효율적인 구조를 가진다. 따라서 CQRS(Command Query Responsibility Segregation)를 적용하면 읽기 성능을 높일 수 있다.
API 컴포지션 패턴은 데이터를 소유하고 있는 각 서비스를 호출한 다음 결과를 조합하여 쿼리 작업을 구현하는 것을 의미한다.
높은 학습 곡선 없이 MSA에서 데이터를 쿼리하는 가장 편리한 방법
경우에 따라 대규모 데이터의 비효율적인 조인이 발생할 수 있다.
CQRS의 주요 목표는 문제를 분리하는 것이다.
사가 패턴을 사용하면 분산 트랜잭션을 사용하지 않고도 MSA에서 데이터 일관성을 유지할 수 있다.
트랜잭션의 관리 주체가 DBMS가 아닌 서비스이다. 따라서 사가 패턴은 보상 트랜잭션 처리도 해줘야 한다.
각 서비스 간 이벤트를 주고 받는 Event Pub/Sub 방식이다. 메시지 큐를 통해 비동기 방식으로 전달하는 것도 가능하다.
1. 메인이 되는 서비스에서 관련 서비스의 로컬 트랜잭션을 호출한다.
2. 트랜잭션이 실패하면 취소된 서비스로부터 보상 이벤트를 발생시켜 보상 트랜잭션을 처리한다.
Orchestrator를 중심으로 한 Invoke/Reply 방식이다.
1. 트랜잭션에 참가하는 각 서비스들의 로컬 트랜잭션은 Orchestrator에 의해 호출되고 상태값이 설정된다.
2. 참가하는 모든 트랜잭션이 처기가 된다면 메인 서비스의 상태가 변경된다.
3. 참가하는 서비스 중 하나라도 트랜잭션 실패하면 Orchestrator는 보상 트랜잭션을 수행한다.
마이크로서비스에서 각 서비스들을 호출하기 위한 여러가지 통신 방법이과 고려해야 될 사항들이 있다.
API에 대한 RPC 메커니즘을 선택하기 전에 서비스와 클라이언트 간의 상호 작용 스타일을 고려하는 것이 좋다.
JSON or XML은 가장 많이 사용되는 텍스트 기반 형식이다.
👍장점
👎단점
Thrift, Protocol Buffers(Protobuf) 및 Avro는 가장 많이 사용되는 바이너리 형식이다.
👍장점
👎단점
호출 패턴으로는 REST / GraphQL / gRPC 와 같은 동기식 통신 메커니즘 또는 AMQP / STOMP 등 비동기식 메시지 기반 통신 메커니즘이 있다.
HTTP URI를 통해 자원을 명시하고 HTTP 메서드를 통해 해당 자원에 대한 CRUD 작업을 처리하는 것
REST API 정의
가장 인기있는 REST 인터페이스 정의 언어는 OpenAPI 입니다.
단일 요청으로 여러 리소스를 가져와야 하는 과제
이러한 확장성 부족으로 인해 발생할 수 있는 언더패치나 오버패치를 해결하기 위해 페이스북의 GraphQL이나 넷플릭스의 Falcor 같은 대체 API 기술이 점점 인기를 얻고 있다.
HTTP 동사에 대한 매핑 작업의 과제
REST API 디자인 문제는 수행하려는 작업을 HTTP 메서드에 매핑하면서 발생한다. PUT을 사용해서 주문을 취소, 수정 등의 업데이트 작업을 해야한다면 다음과 같이 해결할 수 있을 것이다.
gRPC는 구글이 개발한 고성능의 오픈소스 RPC 프레임워크로 MSA 구조안에서 여러 언어로 작성된 서비스들 간의 통신을 지원한다.
HTTP/2를 사용하며 메시지 형식은 바이너리 타입의 protobuf를 사용하기 때문에 상대적으로 적은 페이로드를 사용하고 효율적이다.
👍장점
👎단점
GraphQL은 클라이언트에 데이터를 표시하는 방법을 쿼리로 정의함으로써 단일 요청을 사용하여 여러 리소스를 가져오는 문제를 해결한다.
GraphQL 서버는 클라이언트에 스키마(요청할 수 있는 데이터 모델)를 제공한다.
👍장점
👎단점
서비스는 채널을 구독하고 메시지를 처리한다. 응답이 다시 전송되지 않는다.
클라이언트는 여러 구독자가 읽을 수 있는 채널에 메시지를 게시하고 필요에 따라 여러 서비스가 구독하여 메시지를 처리한다.
Pub/Sub 방식과 Request/Response 방식을 결합하여 더 높은 수준의 상호 작용을 형성한다.
서비스의 외부 API를 설계하는 것은 클라이언트의 다양성으로 인해 더욱 복잡해졌다. 일반적으로 클라이언트는 서로 다른 데이터 요구 사항을 갖기 때문이다.
클라이언트가 서비스를 직접 호출하는 방식으로 API를 디자인할 수 있다.
단점
1. 클라이언트는 보다 상세한 데이터를 위해 여러번의 API 요청을 해야하며 성능 저하를 유발한다.
2. 클라이언트가 각 서비스의 API에 대해 모두 알아야 하므로 캡슐화가 부족하고 클라이언트-서버 간의 강한 의존성을 갖는다.
기본적으로 API 게이트웨이는 외부에서 서비스에 대한 진입점 역할을 하는 서비스이다.
구성 요소로는 요청 라우팅, 프로토콜 변환, API 구성 및 인증, 모니터링 및 속도 제한, 캐싱, 회로 차단 등 다양한 역할을 수행할 수 있다.
요청 라우팅은 API 게이트웨이의 가장 중요한 기능 중 하나이다.
API 게이트웨이는 라우팅 맵을 참조하여 요청을 적절한 서비스로 라우팅한다.
API 게이트웨이는 API Composition을 사용하여 API 작업을 수행할 수 있다. 하나의 요청으로 필요한 데이터 호출 및 조합하여 원하는 결과를 받을 수 있다.
MSA 각 서비스는 REST 및 gRPC를 포함하여 내부적으로 다양한 프로토콜을 사용할 수 있지만 외부에는 REST API를 제공해야 할 수도 있다. 이런 경우 외부와 내부 API간에 프로토콜 변환 작업이 필요하다.
단일 진입점을 갖는 서비스의 문제점은 클라이언트마다 다른 요구사항을 가진다는 것이다. 따라서 클라이언트에 따른 API 게이트웨이 구성으로 적절한 요청을 처리할 수 있다.
cross-cutting 문제의 예는 아래와 같다.
API 게이트웨이 기능을 구현한 여러 서비스가 이미 존재한다.
웹 프레임워크를 사용하여 각 서비스에 대한 요청을 프록시하는 자체 API 게이트웨이를 빌드할 수 있다.
Netflix Zuul
: Zuul은 라우팅, 속도 제한, 인증, cross-cutting 등을 구현하는 Netflix 프레임워크이다. Zuul은 서블릿 필터와 유사한 재사용 가능한 요청 인터셉터 필터 개념을 사용한다.
Spring Cloud Gateway
: Spring Boot, Spring Webflux를 기반으로 하는 API 게이트웨이 프레임워크이다.
참고사이트1 - Microservice Design
참고사이트2 - Microservice Data Design
참고사이트3 - Microservice Communication Design
참고사이트4 - Microservice External Api Design