Skip to content

Commit

Permalink
재권 6주차 ch13, ch14 (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
JaekwonHa committed Feb 26, 2024
1 parent add0bfa commit bdc3b83
Show file tree
Hide file tree
Showing 2 changed files with 293 additions and 0 deletions.
103 changes: 103 additions & 0 deletions ch13/jaekwon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
## 13장. 서비스 기반 아키텍처 스타일

마이크로 서비스 아키텍처 스타일의 일종

기본 토폴로지
* 유저 인터페이스
* 원격 서비스
* 모놀리스 데이터베이스

'서비스'는 큼지막한 단위로 분리해 별도로 배포하는 애플리케이션의 일부
중앙 공유 데이터베이스를 사용할 수도 있고, 별도의 데이터베이스들을 사용할 수도 있다

다양한 토폴로지 구성이 가능
* 단일 모놀리식 유저 인터페이스
* 도메인 기반 유저 인터페이스
* 서비스 기반 유저 인터페이스
* 모놀리식 데이터베이스를 각 도메인 서비스 전용 데이터베이스들로 분리
* 유저 인터페이스와 서비스 사이에 API 레이어(프록시, API 게이트웨이)를 두는




서비스 컴포넌트를 기술 분할 / 도메인 분할 가능
어떻게 설계하든 앞단에 'API 파사드 레이어'가 존재

API 파사드 레이어는 유저 인터페이스로 인입된 비즈니스 요청을 오케스트레이트합니다.
예를 들면, 주문이 접수되면 OrderService에서는 주문 처리, 주문 ID 생성, 결제 처리, 재고 업데이트 등의 일련의 작업을 오케스트레이트합니다.

만약 마이크로서비스 아키텍처에서 처리한다면 별도 배포된 다수의 전용 원격 서비스를 오케스트레이트해야 합니다.
**이것이 서비스 기반 아키텍처와 마이크로서비스 아키텍처의 중요한 차이**

> 결국 마이크로 서비스 아키텍처의 한 타입이고, '서비스'라는게 별도의 애플리케이션(별도의 라이프 사이클을 가지는)으로 분리하는 것은 아닌
데이터 무결성을 보장하기 위한 ACID -> 강한 일관성
마이크로서비스처럼 분산도가 높은 아키텍처에서는 BASE -> 최종 일관성. ACID 레벨의 데이터 무결성 보장 못함
주문을 예로 들면, 주문은 생성했는데, 결제가 실패해서 주문이 남아있게되는 상황도 가능

### 서비스 기반 아키텍처, 마이크로 서비스 아키텍처 비교

* 비즈니스 요청 오케스트레이트
* 서비스 기반 아키텍처: 다른 도메인 서비스들을 메서드 호출하면서 처리하면됨
* 마이크로 서비스 아키텍처: 다른 서버, API를 호출해야됨
* 데이터 무결성 보장
* 서비스 기반 아키텍처: ACID
* 마이크로 서비스 아키텍처: BASE 최종일관성
* 테스트, 배포
* 서비스 기반 아키텍처: 전체 테스트, 전체 배포 필요
* 마이크로 서비스 아키텍처: 일부만 테스트, 배포 가능. 배포가 잘못되어도 영향을 최소화하는게 가능

### 데이터베이스 분할

* 단일 모놀리식 데이터베이스
* 문제점: 테이블 스키마 변경시 모든 서비스 수정 필요
* 그래서 커스텀 공유 라이브러리에 테이블 스키마 보관하긴 하지만..
* 데이터베이스를 논리적으로 분할하면 좀 더 개선 가능
* 공통, 고객, 청구, 주문, 추적. 5개 도메인으로 나누고 공유 라이브러리에 둔다. 필요한 것만 서비스에서 사용한다
* 공통 엔티티 객체를 버전 관리 시스템에서 락킹하고, 수정 권한을 오직 데이터베이스 팀에게만 부여하는 것

> domain module을 아예 별도 모듈로 분리해서 관리하거나..
> flyway, liquibase로 관리하는게 떠오르네..
### 13.5 아키텍처 예시

재활용 시스템
* 견적: 고객이 중고 제품의 가격을 문의
* 수취: 고객이 중고 제품을 보냄
* 감정: 제품의 작동 상태를 감정
* 회계: 보상가를 지불
* 제품 상태: 진행 상황 조회
* 재활용: 재활용 or 재판매
* 리포팅: 임시/정기 재무 리포트 제공

각 도메인 영역을 개별 배포되는 독립적인 도메인 서비스로 구현
데이터베이스를 외부 제공, 내부 제공으로 분리

> 근데 독립적인 도메인 서비스로 배포? 이건 마이크로 서비스 아닌가...그럼 데이터베이스를 같이 쓴다는 점만 다른건가?

### 언제 사용하면 좋을까

어쩌면 가장 실용적인 아키텍쳐

도메인 주도 설계와 궁합이 잘 맞음
서비스를 큰 단위로 나누고 그 범위를 도메인으로 한정 가능

다른 분산 아키텍처에 비해서 ACID 트랜잭션이 잘 보존된다
대부분의 트랜잭션이 특정 도메인 서비스에 한정되므로 모놀리식의 커밋/롤백 트랜잭션이 가능하다

> 근데 마이크로 서비스 아키텍처를 한다고 해도..도메인 단위로 나누지 않나?
당장 주문만 봐도...주문, 쿠폰, 결제 이런 도메인들에 다 걸쳐있어서 모놀리식의 커밋/롤백이 불가능하다

여러 서비스를 조율해서 비즈니스 트랜잭션을 완성하려면
오케스트레이션과 코레오그래피가 모두 필요

오케스트레이션: 트랜잭션의 워크플로를 제어/관리. 중재자 서비스를 따로 두고 여러 서비스를 관리하는 기법
코레오그래피: 중앙의 중재자 서비스 없이 서로 알아서 소통

> Saga Pattern (로컬 트랜잭션의 시퀀스, 이벤트 기반)을 말하는듯..
'분산 트랜잭션 없이도 여러 서비스에서 데이터 일관성을 유지하는게 가능'

> 사가 패턴을 구현하는 두가지 방법
Choreography: 각 로컬 트랜잭션이 다른 서비스에서 로컬 트랜잭션을 트리거하는 도메인 이벤트를 게시합니다.
Orchestration: 오케스트레이터(객체)가 참가자에게 어떤 로컬 트랜잭션을 실행할지 알려줍니다.
190 changes: 190 additions & 0 deletions ch14/jaekwon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
## 14장. 이벤트 기반 아키텍처 스타일

* 요청 기반 모델. request-based model
* 이벤트 기반 모델. event-based model

주요 토폴로지
* 브로커 토폴로지 broker topology
* 중재자 토폴로지 mediator topology

고민이 필요한 부분
* 비동기 통신
* 에러 처리
* 데이터 소실 방지
* 브로드캐스팅
* 요청-응답

* 설계 방식
요청 기반
이벤트 기반
하이브리드 이벤트 기반

### 14.2 브로커 토폴로지

중앙에 이벤트 중재자가 없다
메시지는 메시지 브로커를 통해 브로드캐스팅될뿐

기본 아키텍처
* 시작 이벤트
* 이벤트 브로커
* 이벤트 프로세서
* 처리 이벤트

fire-and-forget + broadcasting -> 확장성

RabbitMQ
ActiveMQ
HornetQ


주문 생성 이벤트 발생 -> 주문 처리 로직 / 이메일 발송 로직 (같은 토픽을 구독 중이면 쉽게 컨슈머를 확장 할 수 있다)
각 도메인들은 본인의 도메인에만 집중할 수 있고, 독립적으로 수행된다
어떤 처리 로직의 성능이 더 필요하면 확장도 독립적으로 가능

![image](assets/image19.png){width="800" height="700"}

* 장점
* 이벤트 프로세서가 디커플링됨
* 확장성 높음
* 응답성 우수
* 성능 우수
* 내고장성 우수
* 단점
* 워크플로 제어 불가능
* 에러 처리 어려움
* 복구 처리 어려움
* 재시작 능력 (어디서부터 재시작? 어디서부터 이벤트를 다시 넣어줄 수가 있나?)
* 데이터 비일관성

### 14.3 중재자 토폴로지

워크플로를 관리/제어하는 중재자가 있는게 핵심

기본 아키텍처
* 시작 이벤트
* 이벤트 큐
* 이벤트 중재자
* 이벤트 채널
* 이벤트 프로세스

이벤트 큐를 통해 먼저 이벤트를 발생시키고, 이벤트 중재자가 프로세서들에게 전달한다
중재자 역시 여러개를 둠으로써 SPF를 줄이고, 전체 처리량, 성능을 높일 수 있다

Apache Camel
Mule EBS
Spring Integration
아파치 ODE
오라클 BPEL 프로세스 관리자
jBPM

![image](assets/image20.png){width="800" height="400"}


이벤트의 복잡도를 기준으로 중재자를 여럿 두는 구성도 가능
(ex. 이벤트 도중 사람이 개입해야하고, 실행 시간이 길다거나)


또한 중재자 토폴로지를 두면 몇가지 작업들은 병렬로 수행이 가능하다.
2,3,4,5(고객알림)를 순서대로 처리하긴 하지만, 그 속에서 병렬로 할 수 있는 것들을 병렬로 제어할 수 있다
한곳에서라도 에러가 발생하면 중재자가 개입하여 조치를 취할 수 있음
> 근데 이벤트 처리를 벙렬로 하는건 브로커 토폴로지에서도 가능할 것 같은데..워크플로 제어는 어렵겠지만
![image](assets/image21.png){width="800" height="500"}

* 장점
* 워크플로 제어
* 에러 처리
* 복구성
* 재시작 능력
* 데이터 일관성
* 단점
* 이벤트 프로세서가 커플링됨
* 확장성 낮음
* 성능 낮음
* 내고장성 좋지 않음
* 워크플로 모델링 복잡함

성능, 확장성이냐 워크플로 제어, 운영의 유리함이냐



### 고민이 필요한 부분

* 비동기 통신
* 이벤트 기반 아키텍처 스타일은 비동기 통신만 한다
* 작업의 완료를 기다리지 않기 때문에 응답속도는 많이 개선될 수 있다
* 동기 통신은 작업의 성공을 보장하지만 비동기는 그렇지 못하다
* 게시글 작성, 주식 매수 등등
* 에러 처리
* 리액티브 아키텍처의 워크플로 이벤트 패턴
* 에러가 발생하면 워크플로 프로세서에게 위임
* 에러 발생 후 block되는게 아니라서 전체 응답성에 영향 X
* 워크플로 프로세서에서 적절한 처리 진행. 원래 큐로 보내거나 처리할 수 없다면 대시보드로 보냄
* 여기서는 주식 bluk 거래를 예로 들어준다
* 근데 주식 매매는 순서가 중요한데, 이벤트 기반 아키텍처에서 순서 보장은 매우 매우 어려운 문제다
* 한가지 방법은 에러가 발생하면 그 계좌에 대한 이벤트들은 따로 담아서 순서를 보장해주는것
* 데이터 소실 방지
* 데이터 소실 케이스
* producer가 이벤트를 produce했지만, broker가 이벤트를 커밋하는데 실패
* -> at least once 보장하도록
* -> 멱등성 프로세서
* consumer가 이벤트를 consume했지만, 처리하는 와중에 실패
* -> 여러가지 커밋 모드를 제공한다. 데이터를 제대로 처리한 시점에 커밋이 되게 해야한다
* consumer가 이벤트를 다 처리하고 데이터베이스에 저장하는 와중에 데이터베이스의 장애
* -> 데이터베이스에 저장을 완료(ACID)했을때, consume commit을 찍는다

위 정리는 내 언어로 다시 적은 것이고, 책에서는 이런 용어로 설명을 해준다
* 동기 전송
* 퍼시스턴트 큐
* 클라이언트 확인 응답 모드
* 최종 참여자 지원
* ACID 트랜잭션지원

* 브로드캐스팅
* 여러 이벤트 프로세서가 높은 수준으로 디커플링 될 수 있도록 해주는 장치
* 프로듀서는 produce하면 끝. 이벤트는 준비되어있으니 필요한 쪽에서 consume하면 됨. 서로 독립적
* 요청-응답
* 도서를 주문할때 주문 ID가 필요하다면? 항공편 예약 확인 번호가 필요하다면?
* 요청 큐 / 응답 큐의 개념을 소개해준다. 동기 요청이 필요한 경우 요청 큐로 요청을 보내고, 응답 큐로 응답이 오기를 기다린다. 물론 이때 blocking wait 상태다
* 구현 방법
* 헤더에 correlation ID 추가
* ID(124)를 일단 만들어서 요청 큐로 던짐
* ID 생성 서비스에서 ID를 CID로 밀고, 실제로 쓰일 ID를 생성해서 ID 자리에 넣어줌
* 프로듀서는 CID로 124인 이벤트가 오면, 이후 작업을 진행
* -> 성능 상 추천되는 방법
* 임시 큐
* 임시 큐는 요청이 들어오면 생성되고, 종료되면 삭제됨
* 프로듀서가 임시 큐를 생성하고(혹은 브로커가 자동 생성) reply-to 헤더를 세팅
* ID를 생성해주고 다시 임시 응답 큐로 던짐
* reploy-to 헤더를 가진 이벤트가 오면 ID를 가지고 이후 작업을 진행
* -> 매번 임시 큐를 생성/폐기해야함. 전체 성능에 영향을 줌

### 설계 방식

* 요청 기반보다 좋은 점
* 동적인 유저 컨텐츠의 응답성이 좋음
* 확장성, 탄력성이 우수
* 민첩성과 변화 관리가 우수
* 적응성과 확장성이 뛰어남
* 응답성과 성능이 좋음
* 실시간 의사 결정이 가능함
* 상황 인지에 따른 반응성이 좋음
* 장단점
* 최종 일관성만 지원됨
* 처리 흐름을 제어하기 곤란함
* 이벤트 흐름의 결과를 예측하기 어려움
* 테스팅, 디버킹이 어려움

기존에 소개된 다른 아키텍처들과의 하이브리드 구성도 가능하다
이벤트 기반 마이크로커널 아키텍처, 이벤트 기반 파이프라인 아키텍처

장점은 병목 지점을 제거하고, back pressure point를 확보 가능


![image](assets/image22.png){width="800" height="600"}

퀀텀이 1 혹은 이상이다
비동기 통신을 하더라도, 단일 데이터베이스 인스턴스를 공유하는 경우 전부 동일한 아키텍처 퀀텀에 포함된다

성능, 확장성, 내고장성이 별점 5개
단순성, 시험성 어려움

0 comments on commit bdc3b83

Please sign in to comment.