Design Patterns

마이크로 서비스 패턴 - 3장. 프로세스 간 통신

FreeEnd 2022. 3. 1. 16:03
반응형

이 블로그는 마이크로서비스패턴 (길벗) 책 내용을 스터디를 위해 정리 한 내용 입니다. 

책구매는 바로가기 에서 구매 가능합니다.

마이크로 서비스 아키텍처 IPC 개요

IPC (Inter-Process Communication, 프로세스간 통신) : 프로세스들 사이에 서로 데이터를 주고 받는 행위, 또는 그에 대한 방법이나 경로를 뜻한다. (위키백과)

 

 이 장에서는 마이크로서비스 / 프로세스간에 통신 방법에 대해서 설명한다. REST, gRPC 등과 같은 동기방식, AMQP, STOMP 등 비동기방식의 통신 방법에 대해서 설명한다.

 

상호작용 스타일

 클라이언트 / 서버간의 인터페이스는 상호작용에 따라 두가지 기준으로 분류할 수 있다.

 

첫번째 일대일 / 일대다 여부이다.

  • 일대일 : 하나의 클라이언트 요청은 하나의 서비스가 처리함.
    • 요청/응답 : 클라이언트는 서비스에 요청하고 응답을 블로킹 상태로 대기함
    • 비동기 요청/응답 : 클라이언트는 서비스에 요청을 하고, 논블로킹 상태로 대기함
    • 단방향 알림 : 클라이언트는 서비스에 요청을 하고, 응답을 기다리지 않음.
  • 일대다 : 각 클라이언트의 요청을 여러개의 서비스가 처리함.
    • 발행 / 구독 : 클라이언트는 메시지를 발행하고, 해당 메시지에 관심이 있는 서비스만 메시지를 소비함
    • 발행 / 비동기 응답 : 클라이언트는 메시지를 발행하고, 주어진 시간동안 서비스 응답을 기다림.

 

두번째, 동기/비동기 여부이다.

  • 동기 (synchronous) : 클라이언트는 자신의 요청에 서비스가 응답할때까지 블로킹 됨. 
  • 비동기  (asynchronous) : 클라이언트는 논블로킹 상태로 다른 업무 수행 가능

 

* 블로킹 / 논 블로킹

블로킹, 논블로킹은  클라이언트가 요청후 응답이 올때까지 제어권을 가지는지, 가지지 못하는지에 대한 관점이다.

다음 그림에서 블로킹은 클라이언트가 서버로 요청을 보내고, 응답이 올때까지 다른 작업을 하지 못하고 대기 하고 있는 상태이며, 논블로킹은 대기하지 않고, 다른 업무를 수행 가능한 상태를 가진다.

 

Blocking / Non-blocking

 

 

마이크로 서비스 API 정의

 잘 설계된 인터페이스는 클라이언트에 영향을 크게 미치지 않고 코드를 고칠수 있다. 때문에 마이크로 서비스 아키텍처에서 가장 중요하다.  서비스 API 는 IDL(Interface Definition Language) 로 정확하게 정의 되어야 한다. 

 

API 발전시키기

 API 는 새 기능 추가나, 기존 기능 변경/삭제등에 따라 계속 변한다. 모놀리식은 같은 어플리케이션은 변경이 발생하면 컴파일 오류등으로 오류를 쉽게 알수 있으나, 마이크로 서비스는 IPC 로 API, 메시지등을 이용하기 때문에 변경하기가 어렵다. 

 

시맨틱 버저닝 (Semantic Versioning specification)

시맨틱 버져닝은 소프트웨어 버전 변경에 대한 규칙이다. 이는 API 나 메시지에서도 유용하게 사용 할 수 있다. 버젼은 다음 기준으로 업데이트한다. 

  • MAJOR : 하위 호환 되지 않는 변경분
  • MINOR : 하위 호환 되는 변경분
  • PATCH : 하위 호환 되는 일반 오류 개선

 요청 속성이 누락되더라도 서비스는 기본값을 제공해야 하고, 서비스가 필요로 하는 항목보다 더 많이 입력되었다 하더라도 클라이언트는 무시 할 수 있어야 한다. 

 하위 호환이 안되는 변경분이 발생 했을경우, 일정기간동안 하위 버전의 API 를 지원 해야 한다. 이를 위해 REST 같은경우 API 의 버젼을 URI 에 포함시키던지, 메시지의 경우 헤더에 버젼을 명시 해야 한다.

 

메시지포맷

IPC 의 핵심은 메시지 교환으로, 메시지 데이터 포맷의 설계는 중요하다. 또 어떤 환경의 서비스에서 사용될지 모르므로 범 언어적 (coss-language) 메시지 포멧을 선택 하는것이 중요하다.

 

텍스트 메시지 포멧

Josn, XML 은 각 항목의 속성명 (name) 을 포함하고 있어 컨슘머는 자신이 필요한 값만 선택해 사용 할 수 있다. 단점은 속성명이 포함됨으로 메시지 길이가 길어 오버헤드가 발생 할 수 있다.

 

이진 메시지 포멧

 이진 메시지 포멧에는 '프로토콜 버퍼' 와 '아브로' 가 있다. 두개 모두 IDL 이 제공 되며, 컴파일러는 직렬화/역직렬화를 통해 코드를 생성 한다.  

 

동기 RPI 패턴 응용통신

RPI (Remote Procedure Invocation, 원격 프로시저 호출) : 별도의 원격 제어를 위한 코딩 없이 다른 주소공간에서 함수나 프로시저를 실행할 수 있게하는 프로세스간 통신 기술이다. (위키백과)

 

동기 RPI 패턴 : REST

 REST 는 HTTP 로 통신하는 IPC 이다. REST는 HTTP 의 METHOD를 이용해 URL 에 참조된 데이터를 가공/처리 한다.

GET 요청은 JSON, XML 등의 포멧으로 결과값을 반환하며, POST는 요청온 데이터를 신규로 생성/저장 한다. 또 PUT 은 기존 데이터를 수정한다. 

 

REST 성숙도

 REST 성숙도는 4단계로 이루어져 있으며, 각 단계를 달성할 수록 REST API 에 가까워진다. (Richardson Maturity Model)

  • 레벨 0 (1 URL, 1 HTTP Method)
    단순하게 POX (Plain Old XML) 을 주고 받는 RPC 스타일의 시스템을 말한다. 단 하나의 endpoint 만 사용하고, 전달 되는 매개변수를 통해 여러 동작을 하게 된다. 또 매개변수를 BODY 로 전달 하기 위해 HTTP METHOD 는 POST 가 된다. 

  • 레벨 1 (N URL, 2 HTTP Method)
    단일 endpoint 가 아닌, 개별 리소스별 고유한 URI로 통신한다. HTTP METHOD 는 GET 과 POST 만 사용하며 Response 에서 error 도 staus code 를 200으로만 처리한다.
    헤더에 Contect-Type 이나 Cache 에 관한 정보도 제공 되지 않는다.

  • 레벨 2 (N URL, 4 HTTP Method)
    2단계에서는 GET, POST, PUT, DELETE 를 사용해 CRUD 하며, 처리 결과에 따라 status code 도 담겨서 반환한다.
    GET 은 cashe 등을 제공할 수 있다.

  • 레벨 3 (Hypermedia as Engine of Application State)
    이 단계까지 와야 진정한 REST API 이다. 모든 endpoint 를 최초 진입점이 되는 URI 를 통해 Hypertext Link 형태로 제공된다. GET 요청으로 반환된 Request 에 리소스에 대한 액션의 링크도 포함되서 나가는 형태이다. 이 요청으로 다음 진행 할 수 있는 액션을 클라이언트에서 알수 있다.

REST API

REST 는 IDL 이 없다.
이 IDL 을 도와주는 오픈소스로는 스웨거가 있고, 스웨거는 stub, skeleton 을 생성하는 툴이 포함된다.

 

요청 한번으로 많은 리소스를 가져오기 어렵다.

REST는 한가지 요청에 한가지 서비스만 하므로, 다양한 데이터를 얻기 위해선 필요한 만큼 API 를 호출 해야 한다.

이런 점을 해결하기 위해서는 연관 리스소드 조회하도록 API 를 개발하는 것이다.  예를들어 주문 조회의 경우, 매개변수에 주문자 요청 변수도 함께 전달해 주문자 정보까지 함께 받는 식이다.

 

작업을 HTTP 동사에 매핑 하기 어렵다.

REST 는 데이터를 수정할때 PUT 을 쓰지만, 수정하는 목적이 다를 수 있다. 주문 변경 요청시 PUT MTHOD 는 명확하지만 취소인지 반품인지 등이 명확하지 않다. 이를때 URI 에 행위를 명시해 보내는 방법이 있다.

예 ) /order/{orderid}/cancel,  /order/{orderid}/revise 등

 

 

REST 의 장/단점

  •  장점
    사용성이 단순하다.
    POSTMAN등 테스트할수 있는 다양한 방법등이 있다.
    브로커가 없어 개발이 쉽다. 등

  • 단점
    요청 / 응답만 지원한다.
    가용성이 떨어진다. (서버 / 클라이언트가 모두 운용 중이여야 한다)
    URI 를 알고 있어야 한다. 등


동기 RPI 패턴 : gRPC

gRPC (Google Remote Procedure Calls, 구글 원격 프로시저 호출)는  구글이 최초로 개발한 오픈 소스 원격 프로시저 호출 (RPC) 시스템이다. 전송을 위해 HTTP/2를, 인터페이스 정의 언어 프로토콜 버퍼를 사용하며 인증, 양방향 스트리밍 및 흐름 제어, 차단 및 비차단 바인딩, 취소 및 타임아웃 등의 기능을 제공한다. (위키백과)

 

 

 다양한 언어로 클라이언트 / 서버를 작성 할 수 있다. IDL 로 프로토콜 버퍼(Protocol Buffer)를 사용한다. 프로토콜 버퍼는 xml 의 문제점을 개선하기 위해 제안된 IDL 이다.

 

프로토콜 버퍼는 구조화된 데이터를 직렬화하여 압축해 전송하기때문에 xml 에 비해 파일 크기가 3~10배 작으며, 속도가 20~100배 정도 빠르다. 

 

 프로토콜 버퍼는 xml 스키마와 같은 .proto 파일을 이용해 protocol buffer 메시지 타입을 정의하고, 이를 프로토콜 컴파일러를 통해 클라이언트 쪽 stub 및 서버 skeleton 을 생성 할 수 있다.  이렇게 데이터 주고 받는 형식이 코드로 생성되기 때문에 따로 API 문서가 필요 없다. 

 

단, HTTP/2.0 를 지원해 다양한 HTTP/2.0 기능을 사용할 수 있지만, HTTP/2 지원하지 않는 시스템에서는 사용할 수 없다.

 

부분 실패 처리 : 회로차단기 패턴

회로 차단기, 연속 실패 횟수가 주어진 임계치를 초과하면 일정시간동안 호출을 즉시 거부하는 패턴이다.

 

 분산 시스템은 서비스가 다른 서비스를 동기 호출할 떄마다 부분 실패 할 수 있다. 특정서버의 점검이던 실패이던, 하나의 시스템이 장애가 생기면 클라이언트는 응답대기도증 블로킹 되어, 잠정적으로는 전체 시스템의 장애를 초래 할 수 있다. 따라서 이러한 케이스를 방어 해야 한다.

 

견고한 RPI 프록시 설계

  • 네트워크 타임아웃 : 무한정 블로킹을 방어하기 위해 TIME-OUT 을 설정한다.
  • 미처리 요청 개수 제한 :  클라이언트가 특정 서비스에 요청 가능한 임계치를 설정
  • 회로 차단기 패턴 : 에러율이 특정 수치를 초과하면, 이후 요청건은 무조건 실패 하도록 설정

불능 서비스 복구

 무응답 원격 서비스를 어떻게 복구하면 좋을지는 그떄그때 상황에 맞게 판단 해야 한다.

 

 

 

서비스 디스커버리

 API 호출시에는 서비스 인스턴스의 네트워크 위치 (IP, 도메인 / 포트)을 알고 있어야한다. 요즘같은 클라우드 시스템에서는 확장, 축소, 변경 등 네트워크 위치가 시시 각각 변하기 때문에 네트워크 위치를 식별하는 일이 간단치 않다.

 

 이를 대비해 다음과 같은 방법이 필요하다.

 서비스 인스턴스의 네트워크 위치를 DB화하여 '서비스 레지스트리'에 관리한다. 서비스 인스턴스가 시작, 종료될때마다 서비스 레지스트리에 등록/삭제한다 클라이언트는 서비스 레지스트리를 조회하여 등록되어있는 해당 서비스의 가용서버로 요청을 호출 한다. 

 

 

애플리케이션 수준의 서비스 디스커버리 패턴 적용

서비스 인스턴스가 시작될때, 자신의 위치를 서비스 레지스트리에 등록하고, 클라이언트는 전체 서비스 인스턴스 목록을 가져와 그중 하나로 요청 (라운드로빈 / 랜덤) 을 한다.

넷플릭스의 유레카가 애플리케이션 수준의 서비스 디스커버리이다.

 

플랫폼에 내장된 서비스 디스커버리 패턴 적용

 도커나 쿠버네티스등 최신 배포플랫폼에는 서비스 레지스트리, 서비스 디스커버리등이 탑재 되어 있다.

클라이언트가 DNS, VIP 등을 요청하면 배포 플랫폼이 가용인스턴스중 하나로 요청을 라우팅 한다.

 

  • 서드파티 등록패턴 : 서드파티가 서비스 인스턴스를 서비스 레지스트리에 자동 등록한다.
  • 서버쪽 디스커버리 패턴 : 클라이언트가 서비스 디스커버리를 담당한 라우터에 요청한다.

 

비동기메시징 패턴 응용 통신

 메시지를 비동기적으로 주고 받는 통신 방식이다. 브로커레스 (Brokerless, 브로커가 없는) 방식과 브로커가 존재하는 방식, 두가지가 존재 한다.

 

메시징 개요

메시지

메시지는 헤더 (Header), 본문 (Body), 로 구성된다. 헤더는 메시지에관한 메타데이터를 포함한다.

 

메시지의 종류는 다양하다.

  • 문서 (Document) : 데이터만 포함된 평문
  • 커맨드 (Command) : RPC 와 동등한 메시지
  • 이벤트 (event) :  이벤트 발생 메시지

 

메시지 채널

메시지는 채널을 통해 교환된다. 

  • 점대점 (Point to Point) : 채널을 읽는 컨슘머중 하나만 지정하여 전달
  • 발행-구독 (publish - subscribe) : 같은 채널을 바라보는 모든 컨슘머에 메시지를 전달.

 

메시징 상호작용 스타일 구현

요청/응답 및 비동기 요청/응답

동기 요청/응답은 서비스가 즉시 응답 할것으로 클라이언트가 기대하고, 비동기 요청/응답은 기대하지 않는다. 메시징은 비동기 요청으로 제공되지만 원한다면 클라이언트를 블로킹 할 수도 있다.

 클라이언트 / 서비스는 요청을 점대점 채널로 보내고, 비동기적으로 응답을 기다린다. 이때 요청한 메시지와 응답받은 메시지가 짝이 맞아야 한다. 이는 요청한 메시지에 포함된 메시지ID를 응답메시지에 보내어 맞추어 보며 확인한다.

 

단방향 알림

클라이언트가 점대점 채널로 메시지를 보내면 해당 채널을 소유하고 있는 서비스가 메시지를 구독해서 처리하는 방식이다. 단방향이므로 메시지에 대한 응답은 하지 않는다.

 

발행/구독

 클라이언트는 여러 컨슘머가 존재 하는 채널로 메시지를 발행하고, 각 서비스는 관심 있는 이벤트 채널만 구독한다.

 

발행 / 비동기 응답

 클라이언트는 응답 채널 헤더가 명시된 메시지를 발행/구독 채널에 발행하고, 컨슘머는 메시지ID가 포함된 응답메시지를 지정된 응답 채널에 쓴다. 클라이언트는메시지 ID로 응답을 취함하여 응답 메시지와의 요청을 맞춰본다.

 

메시징 기반 서비스의 API 명세 작성

 비동기 API 명세는 메시지의 채널명 과 메시지의 타입, 포멧 (JSON, XML , 프로토콜버퍼 등) 을 기술 해야 한다. 

비동기 작업 문서화

  • 요청/비동기 응답 스타일 API
    • 커맨드 메시지 채널
    • 커맨드 메시지의 타입과 포멧
    • 응답메시지의 타입과 포멧
  • 단방향 알림 스타일API 
    • 커맨드 메시지 채널
    • 커맨드 메시지의 타입과 포멧

 

발행 이벤트 문서화

  • 발행/구독 스타일
    • 이벤트 채널
    • 이벤트 메시지의 타입과 포멧

 

메시지 브로커

 메시지 브로커는 서비스가 서로 통신할 수 있게 해주는 인프라 서비스 이다. 

브로커리스 메시징 (Brokerless)

브로커리스는 메시지를 직접 교환하는 방식이다. 예를 들면 ZeroMQ 가 있다.

브로커리스의 장점

  • 네트워크 트래픽이 가볍고, 지연시간이 짧다
  • 브로커가 없어 병목점이 없다.
  • 브로커 관리 리소스가 들지 않는다.

브로커리스의 단점

  • 서비스가 서로의 위치를 알고 있어야 하므로 디스커버리 매커니즘을 사용해야 한다.
  • 송신/수신자가 모두 가용상태로 존재 해야 한다.
  • 전달 보장 (장애대처) 를 할 수 없다.

 

브로커 기반 메시징 개요

브로커 기반의 가장 큰 장점은 컨슘머의 위치를 알 필요가 없으며, 컨슘머가 처리 할 수 있을때까지의 버퍼링도 담당 할 수 있다. 이로인해 장애에 대한 복구 등에 처리가 가능한다.

 가장 많이 사용되는 메시지 브로커는 ActiveMQ, RabbitMQ, Kafka 등이 있다.

 

 메시징 서비스를 도입할 때, 다음과 같은 기능등을 검토 해야 한다.

  • 프로그램 언어 지원여부
  • 메시징 표준 지원여부
  • 메시지 순서
  • 전달 보장
  • 영속화
  • 내구성
  • 확장성
  • 지연시간
  • 컨슘머 범용성

 

메시지 브로커로 메시지 채널 구현

 --

브로커 기반 메시징의 장단점

장점

  • 느신한 결합 : 클라이언트는 서비스 인스턴스를 몰라도 된다.
  • 메시지 버퍼링 : 컨슘머가 처리 가능한 시점까지 메시지를 버퍼링 한다.
  • 유연한 통신 : 모든 상호작용 스타일을 지원한다.
  • 명시적 IPC : ?

단점

  • 성능병목가능성 : 메시지 브로커가 병목점이 될 수 있다.
  • 단일 장애점 가능성 : 메시지 브로커가 장애가 될 경우 시스템 전체에 영향이 발생한다.
  • 운영 복잡도 부가 : 브로커 역시 운영 리소스가 필요하다.

 

수신자경합과 메시지 순서유지

 메시지는 발생 순서와 같게 서비스에 도착 해야 한다. 또, 중복으로 발생했을때 중복 처리 되지 않도록 프로세스화 되어야 한다.

 

 한 시스템을 스케일 아웃하여 서비스 인스턴스가 3개가 있다고 했을 때 한 채널에 메시지가 순서대로 A라는 이벤트가 1,2,3 의 상태로 변경 되었을 경우, 각 인스턴스는 순서대로 메시지를 컨슘 할 수 있지만 네트워크, 장애등의 이유로 이벤트는 2,1,3 순서대로 수신 되거나, 2번만 누락되는 등의 일이 발생 할 수 있다. 

 

이를 해결하기 위한 다음과 같은 방법이 있다.

  1. 채널을 샤드한다. 각 샤드는 개별 채널 처럼 동작한다.
  2. 송신자는 메시지 헤더에 샤드키를 지정한다.
  3. 브로커는 여러 수신자 인스턴스를 묶어 동일한 수신자 처럼 취급 한다. (KAFKA 에서 컨슘머 그룹이라고 한다)

 

 

 하나의 키를 같는 메시지는 키를 샤드한 채널로만 메시지가 발행되고, 컨슘머는 하나의 채널에서만 순서대로 메시지를 받을 수 있어 순서가 보장 된다.

 

중복 메시지 처리

 일반적으로 메시지는 유일한 메시지가 생성되나 장애 발생, 장애에대한 복구등으로 인해 동일한 메시지가 중복으로 발생, 소비 될 수 있다. 이러한 문제를 해결하기 위한 매커니즘이 필요하다.

 

멱등한 메시지 핸들러 작성

 동일한 입력값이 반복적으로 발생/호출되도 아무런 부수적 효과가 없을때 이를 멱등하다 라고 한다. 어플리케이션에서도 멱등한 로직을 만들면 중복 메시지도 문제가 없다. 이러한 핸들러 작성이 필요하다.

 

메시지 추적과 중복 메시지 솎아내기

 메시지의 메시지 ID를 DB에 저장하는것도 훌륭한 방법이다. 메시지 처리시 메시지 ID를 특정 테이블에 저장하고, 다음 메시지 수신사 해당 ID를 특정 테이블에 있는지 조회하여 동일하면 무시하는 방법이다.

 

 

트랜잭셔널 메시징

DB를 업데이트하고 메시지를 발행 한뒤 트랜잭션이 종료 되어야 한다. 혹시 DB는 저장되지 않고 메시지가 나가던지, DB는 저장되었는데 메시지가 나가지 않는 등의 일이 벌어질 수 있기때문이다.

 

DB테이블을 메시지 큐로 활용

RDBMS 기반의 어플리케이션의 경우 DB 테이블을 임시 메시지 큐로 사용하는 아웃박스(OUTBOX) 패턴이 있다.

비지니스 로직에서 수정/삭제가 발생했을때 동일 트랜잭션에서 OUTBOX 테이블에 메시지를 삽입한다. 로컬 ACID 이기때문에 원자성이 보장된다. 또 OUTBOX 는 큐역할도 대신 하기때문에 순서성도 보장 된다.

 

 

메시지를 DB에서 브로커로 옮기는 방법은 다음 두가지 이다.

이벤트 발행 : 폴링 발행기 패턴

 OUTBOX 테이블에서 미발행 메시지를 입력 순서에 따라 조회해 메시지를 발행후 삭제한다.

가장 단순한 방법이고 쉽지만, 자주 DB를 폴링 하기때문에 DB에 조회 리소스가 발생한다.

 

이벤트 발행 : 트랜잭션 로그 테일링 패턴

 DB트랜잭션 로그를 테일링 하는 방법이 있다. 어플리케이션에서 DB로 커멧된 업데이트는 로그로 남는다. 이 로그를 읽어 메시지로 발행하는것이 트랜잭션 로그 테일링 패턴이다.

 오픈소스로 다음과 같이 공개 되어 있다.

  • 디비지움 (Debezium)
  • 링크드인 데이터버스 (LionkedIn Databus)
  • DynamoDB 스트림즈 (streams) 
  • 이벤추에이트 트램 (Eventuate Tram) 

 

메시징 라이브러리/프레임워크

기본메시징

도메인 이벤트 발행

커맨드/응답 메시징

 

비동기메시징으로 가용성 개선

동기 통신으로 인한 가용성 저하

동기 프로토콜을 이용하면 HTTP 클라이언트는 요청이 응답할때까지 기다려야 하므로 가용성은 저하될 수 밖에 없다. 하나의 서비스가 두개 이상의 서비스를 연속적으로 호출 할 경우, 두 서비스중 하나라도 중단되면 해당 서비스는 중단 된다. 그렇기 때문에 더 많은 서비스가 요청에 개입될 수록 가용성은 점점 낮아진다.

 

 

 

동기 상호 작용 제거

비동기 상호 작용 스타일

 

 

데이터 복제

 REST 와 같은 동기 프로토콜을 사용하여 요청 즉시 응답해야 하는 API 도 있을것이다. 이럴때는 서비스에 데이터를 복제 하면 가용성을 높일 수 있다.

 데이터를 소유한 서비스가 데이터 변경시 변경된 이벤트를 발행하고, 필요한 서비스에서 이를 수신해 로컬 레플리카 DB에 최신 데이터를 유지 한다.  이렇게 되면 다른 서비스의 데이터를 조회 하기 위해 조회 하는 상호 작용이 제거되어 가용성이 증가되고 성능도 높일 수 있다. 하지만 방대한 데이터를 관리하는 대규모 시스템에서는 복제 해야 할 데이터가 너무 크기때문에 실제로 실용적이지 못한다.

 

 

응답 반환 후 마무리

 요청 처리도중 동기 통신을 제거하려면 다음과 같이 한다.

  • 로컬에서 가용한 데이터만 가지고 검증함
  • 메시지를 OUTBOX 테이블에 삽입하는 식으로 DB를 업데이트
  • 클라이언트에 응답을 반환

이렇게 하면 다른 서비스와 상호 작용 없이 느슨한 결합을 유지 할 수 있다.

 

 

 주문 서비스의 경우 Pending상태를 생성해 비동기 처리를 할 수 있다.

주문을 Pending 상태로 생성하고, valdation 은 동기로 처리한뒤 실제 결과는 비동기로 입력받아 각 VALIDATION 에 대한 처리를 상태값으로 관리한다. 최종적으로 비동기 응답을 모두 받은뒤 주문의 상태를 처리 하면 된다.

이때 다른 서비스가 장애가 나더라도 주문이 후속 처리 되지않고, 복구되어 응답을 받았을때 다시 상태가 처리 되므로 가용성이 높아진다.

반응형