Service Instance per Host Pattern
(호스트별 단일 서비스 인스턴스 패턴)

Microservice를 배포하는 또 다른 방법은 호스트 별로 하나의 서비스 인스턴스를 배포하는 패턴이다. 이 패턴을 사용할 때, 각 서비스 인스턴스는 자체 호스트에서 독립적으로 실행된다. 이 패턴에는 VM(Virtual Machine)별 서비스 인스턴스 배포 패턴과 컨테이너별 서비스 인스턴스 배포 패턴의 2가지 다른 특별한 유형이 있다.

Service Instance per Virtual Machine Pattern
(Virtual Machine별 서비스 인스턴스 패턴)

VM별 서비스 인스턴스 배포 패턴을 사용하면, 각 서비스를 아마존 EC2 AMI처럼 VM 이미지로 패키징한다. 가거 서비스 인스턴스는 VM 이미지를 사용하여 실행되는 VM(예를 들면, EC2 인스턴스)이다. 다음 다이어그램은 이 패턴의 구조를 보여준다.

사용자 삽입 이미지


이것은 Netflix에서 비디오 스트리밍 서비스를 배포하기 위해 사용했던 기본 접근 방법이다. Netflix는 Aminator를 사용한 EC2 AMI로 각 서비스를 패키징한다. 실행되는 각 서비스 인스턴스는 EC2 인스턴스이다.

자체 VM을 구축하는데 사용할 수 있는 다양한 툴이 있다. EC2 AMI로 서비스를 패키징하기 위해 Aminator를 호출하여 Continuous Integration (CI, 예 : Jenkins) 서버를 구성할 수 있다. Packer.io는 자동으로 VM 이미지를 생성하기 위한 또다른 옵션이다. Aminator와는 다르게, Packer.io는 EC2, DigitalOcean, ViurualBox, VMWare를 포함하여 다양한 가상화 기술을 지원한다.

Boxfuse 회사는 위에서 언급한 VM들의 단점을 극복한 강력한 VM 이미지 구축 방법을 가지고 있다. Boxfuse는 Java Application을 최소한의 VM 이미지로 패키징한다. 이러한 이미지들은 빌드가 빠르고, 부팅도 빠르고, 제한된 공격 영역을 노출하기 때문에 더 안전하다.

CloudNative는 EC2 AMI 생성을 위한 SaaS 제공 업체인 Bakery를 보유하고 있다. Microservice 테스트 단계 패스 이후 Bakery를 호출하도록 CI 서버를 구성할 수 있다. Bakery는 서비스를 AMI로 패키징한다. Bakery와 같은 SaaS 제공 업체를 사용하는 것은 AMI 생성 인프라 구성에 귀중한 시간을 낭비할 필요가 없다는 것을 의미한다.

VM별 단일 서비스 인스턴스 배포 패턴은 많은 장점이 있다. VM의 주요 이점은 각 서비스 인스턴스가 완벽히 독립되어 실행된다는 것이다. 고정된 CPU와 메모리 용량을 가지고, 다른 서비스의 리소스를 도용할 수 없다.

Microservice를 VM으로 배포하는 또다른 장점은 성숙한 클라우드 인프라를 활용할 수 있다는 것이다. AWS와 같은 클라우드는 로드 밸런싱(부하 분산)이나 Auto-Scaling(자동 확장)과 같은 유용한 기능을 제공한다.

또다른 큰 장점은 서비스 구현 기술을 캡슐화 한다는 것이다. 일단 VM으로 서비스가 패키징되면, Black Box(블랙 박스)가 된다. VM을 관리하는 API는 서비스를 배포하는 API가 된다.(VM 관리 API로 서비스를 배포할 수 있다.) 훨씬 간단하고 안정적으로 배포하게 된다.

그러나, Service Instance per Virtual Machine (VM별 서비스 인스턴스 배포) 패턴은 몇 가지 단점이 있다. 한가지 단점은 리소스 사용 관점에서는 덜 효율적이다. 각 서비스 인스턴스는 OS를 포함하여 전체 VM 오버헤드가 있다. 더우기, 일반적인 공용 IaaS에서는 VM은 고정된 크기를 가지고 있으며, VM을 충분히 활용하지 못할 수도 있다.

다른 관점에서 보면, 일반적으로 공용 IaaS는 VM의 사용 여부와 무관하게 과금한다. AWS와 같은 IaaS는 Auto-Scaling을 지원하지만, 수요 변화에 빠르게 반응하는 것은 어렵다. 결과적으로, VM을 과도하게 준비해야 하므로 배포 비용이 증가하게 된다.

이 접근 방법의 또 다른 단점은 새로운 버전의 서비스를 배포하는 것이 일반적으로 느리다는 것이다. VM 이미지는 크기 때문에 빌드 속도가 느리다. 또한, 크기 때문에 VM은 인스턴스화 하는 것도 느리다. 그리고 OS는 시작하는데 약간 시간이 걸린다. 그러나, Boxfuse로 빌드된 경량화된 VM들이 존재하기 때문에 보편적이라고 말하기는 어렵다.

Service Instance per Virtual Machine 패턴의 또다른 단점은 일반적으로 여러분(혹은 조직의 다른 사람)이 많은 구분되지 않은 들어올리기 힘든 일을 감당한다는 것이다. VM을 빌드하고, 관리하는 오버헤드를 처리하기 위해 Boxfuse와 같은 툴을 사용하지 않는다면, 모두 여러분의 책임이다. 이렇게 필수적이지만 시간을 소모하는 활동은 핵심 비즈니스에서 (여러분의 관심사를) 다른 곳으로 돌린다.

자, 이제 더 가볍고 VM의 많은 이점을 갖는 Microservice 배포에 대한 대안을 살펴보자.

Service Instance per Container Pattern
(컨테이너별 서비스 인스턴스 패턴)

Service Instance per Container (컨테이너별 서비스 인스턴스) 패턴을 사용하는 경우, 각 서비스 인스턴스는 자체 컨테이너에서 동작한다. 컨테이너는 OS 수준 가상화 메커니즘이다. 컨테이너는 샌드박스 내에서 실행되는 하나 이상의 프로세스로 이루어져 있다. 프로세스 관점에서, 프로세스는 자체 포트 네임스페이스와 루트 파일 시스템을 가지고 있다. 컨테이너별로 메모리와 CPU 리소스를 제한할 수 있다. 어떤 컨테이너 구현체에는 I/O 비율 제한도 있다. 컨테이너 기술의 예로 Docker와 Solaris Zones가 있다.

다음 다이어그램에서는 이 패턴의 구조를 보여준다.

사용자 삽입 이미지


이 패턴을 사용하기 위해서는 서비스를 컨테이너 이미지로 패키지해야 한다. 컨테이너 이미지는 Application과 서비스 실행에 필요한 라이브러리들로 구성된 파일 시스템 이미지이다. 일부 컨테이너 이미지는 완전한 리눅스 루트 파일 시스템으로 이루어져 있다. 다른 것들은 더 가볍다. 예를 들면, Java 서비스를 배포하기 위해서 Java Runtime(아마도 Apache Tomcat 서버)과 컴파일된 Java Application을 포함하여 컨테이너 이미지를 빌드 한다.

일단, 서비스를 컨테이너 이미지로 패키징하면 하나 이상의 컨테이너를 실행한다. 각 실제 서버 혹은 가상 서버에서 일반적으로 여러 개의 컨테이너를 실행한다. 컨테이너들을 관리하기 위해서 Kubernetes나 Marathon과 같은 클러스터 관리자를 사용할 수도 있다. 클러스터 관리자는 호스트를 리소스 풀(pool)로 다룬다. 컨테이너가 필요로하는 리소스와 각 호스트에서 이용가능한 리소스를 기반으로 각 컨테이너를 어디에 배치할 지를 결정한다.

Service Instance per Container(컨테이너별 서비스 인스턴스) 패턴은 장단점이 모두 있다. 컨테이너의 장점은 VM과 유사하다. 서비스 인스턴스가 서로 격리되어 있다. 각 컨테이너가 사용하는 리소스를 쉽게 모니터링 할 수 있다. 또한 VM처럼, 컨테이너는 구현된 서비스를 캡슐화한다. 서비스를 관리하기 위한 API로 컨테이너 관리  API를 제공한다.

그러나 VM과는 다르게, 컨테이너는 가벼운 기술이다. 컨테이너 이미지는 일반적으로 매우 빠르게 빌드된다. 예를 들면, 랩톱에서 Spring Boot Application을 Docker 컨테이너로 패키징하는데 약 5초가 걸린다. 지루한 OS 부팅 메커니즘이 없기 때문에 컨테이너는 매우 빠르게 시작된다. 컨테이너가 시작될 때, 서비스도 시작된다.

컨테이너를 사용하는 것에는 몇 가지 단점이 있다. 컨테이너 인프라스트럭처가 급속도로 성숙하고 있으나, VM만큼 성숙하지는 못했다. 또한, 컨테이너들은 호스트 서버 OS의 커널을 서로 공유하므로 VM만큼 안전하지 못하다.

컨테이너의 또다른 단점은 컨테이너 이미지를 관리하는데 구분되지 않은 들어올리기 힘든 책임이 있다는 것이다. 또한 Google Container Engine이나 Amazon EC2 Container Service(ECS)와 같은 호스팅되는 컨테이너 솔루션을 이용하지 않는다면, 컨테이너 인프라와 실행되는 VM 인프라를 관리해야만 한다.

그리고, 컨테이너는 종종 VM 단위 과금되는 인프라에 배포된다. 결과적으로, 앞에서 언급한 것처럼, 급증한 부하를 처리하기 위하여 과도하게 VM을 준비하여 초과 비용을 초래할 수도 있다.

흥미롭게도, 컨테이너와 VM 사이의 차이점이 모호해질 수도 있다. 앞에서 언급한 것처럼, Boxfuse VM은 빠르게 빌드하고 빠르게 시작할 수 있다. Clear Container 프로젝트의 목표는 가벼운 VM을 생성하는 것이다. unikernel에 대한 관심도 증가하고 있다. Docker, Inc는 최근에 Unikernel Systems를 인수했다.

또한 Server-less 배포에 대한 새롭고 인기가 증가하고 있는 개념도 있다. 이 개념은 서비스를 배포하기 위해 컨테이너나 VM 중에 선택하는 이슈를 회피하는 접근 방법이다. 다음에서 살펴보자

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/779


Multiple Service Instances per Host Pattern
(호스트별 다중 서비스 인스턴스 패턴)

Microservice를 배포하는 한가지 방법은 하나의 Host에 여러 개의 서비스 인스턴스를 배포하는 패턴이다. 이 패턴을 사용할 때, 하나 이상의 실제 혹은 가상 호스트를 준비하고, 각 호스트에 여러 개의 서비스 인스턴스를 실행한다. 여러 면에서, 이것은 Application을 배포할 때 전통적인 접근법이다. 각 서비스 인스턴스는 하나 이상의 호스트에서 잘 알려진 포트로 동작한다. 호스트 컴퓨터는 마치 애완 동물처럼 다루어진다.

다음 다이어그램은 이 패턴의 구조를 보여준다.

사용자 삽입 이미지


이 패턴 기반 몇 가지 변형 패턴이 있다. 한가지 변형 패턴은 각 서비스 인스턴스가 하나의 프로세스나 프로세스 그룹이 되는 것이다. 예를 들면, Apache Tomcat 서버에 웹 어플리케이션으로 Java service instance를 배포할 수 있다. Node.js 서비스 인스턴스는 하나의 부모 프로세스와 하나 이상의 자식 프로세스로 구성될 수 있다.

다른 변형 패턴은 동일한 프로세스나 프로세스 그룹에서 여러 개의 서비스 인스턴스를 실행하는 것이다. 예를 들면, 하나의 Apache Tomcat 서버에 여러 개의 Java Web Application을 배포할 수 있다. 또는 동일한 OSGI 컨테이너에 여러 개의 OSGI 번들을 실행할 수도 있다.

Multiple Service Instance per Host 패턴에는 장단점이 모두 있다. 한가지 주요 장점은 리소스 사용이 상대적으로 효율적이라는 것이다. Multiple Service Instance가 서버와 OS를 공유한다. 프로세스나 프로세스 그룹이 여러 개의 서비스 인스턴스를 실행하는 경우에 훨썬 더 효율적이다. (예를 들어, 동일한 Apache Tomcat Server와 JVM을 여러 개의 웹 어플리케이션이 공유하는 경우)

이 패턴의 또다른 장점은 서비스 인스턴스를 상대적으로 빠르게 배포하는 것이다. 간단히 서비스를 호스트에 복사하고 시작하면 된다. 만약 서비스를 Java로 개발했다면, JAR나 WAR를 복사한다. Node.js나 Ruby와 같은 다른 언으로 개발했다면, 소스 코드를 복사한다. 어느 경우라도, 네트워크를 통해서 복사된 바이트 수는 상대적으로 작다.

또한 오버헤드가 없기 때문에, 서비스를 시작하는 것은 일반적으로 굉장히 빠르다. 서비스가 자체적으로 프로세스인 경우, 시작하기만 하면 된다. 그렇지 않을 경우에, 만약 서비스가 동일한 컨테이너 프로세스나 프로세스 그룹에서 실행되는 여러 개의 인스턴스 중 하나라면, 컨테이너에 동적으로 배포하거나 컨테이너를 재시작한다.

이러한 장점의 호소에도 불구하고, Multiple Service Instance per Host 패턴에는 몇 가지 중요한 단점이 있다. 한가지 주요 단점은 각 서비스 인스턴스가 분리된 프로세스가 아니라면, 서비스 인스턴스의 격리가 거의 혹은 전혀 없다는 것이다. (서로 영향을 주고 받아서 한가지 서비스 인스턴스의 오류가 인해 전체가 영향을 받음) 각 개별 서비스 인스턴스의 리소스 사용율을 정확하게 모니터링 할 수 있으나, 각 인스턴스가 사용하는 리소스를 제한할 수는 없다. 잘못 동작하는 서비스 인스턴스가 호스트의 전체 메모리나 CPU를 사용할 수도 있다.

여러 개의 서비스 인스턴스를 동일한 프로세스에서 실행하는 경우에는 격리가 전혀 없다. 예를 들면, 모든 인스턴스들은 동일한 JVM Heap을 공유한다. 오동작하는 서비스 인스턴스는 동일한 프로세스내 실행되고 있는 다른 서비스들을 쉽게 중단시킬 수 있다. 또한, 각 서비스 인스턴스가 사용하는 리소스를 모니터링할 방법도 없다.

이 접근법의 또다른 심각한 문제는 서비스를 배포하는 운영 팀이 어떻게 해야 하는지에 대한 상세한 세부 사항을 알고 있어야만 한다는 것이다. 서비스들은 다양한 언어와 프레임워크로 작성될 수 있기 때문에 개발팀이 운영팀과 공유해야만 하는 많은 세부사항들이 있다. 이러한 복잡성은 배포하는 동안 오류 발생 리스크를 증가시킨다. 보는 것처럼, 친숙함에도 불구하고 Multiple Service Instance per Host 패턴은 몇 가지 중대한 단점이 있다. 이제 이러한 문제들을 피하는 다른 Microservice 배포 방법에 대해 알아보자.
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/778


Choosing a Microservices Deployment Strategy
(Microservice 배포 전략 선택)

이것은 Microservice로 Application을 작성하는 시리즈 중에서 여섯번째 글이다. 첫번째 글에서는 Microservice Architecture Pattern을 소개하고, Microservice 사용에 대한 장단점을 논의했다. 그 다음 글에서는 Microservice Architecture의 다양한 측면 : API Gateway 사용, 프로세스간 통신, 서비스 검색, Event-Driven 데이터 관리 등에 대해서 살펴보았다. 이번 글에서는 Microservice 배포 전략에 대해서 살펴보자.

Motivations
(동기)

Monolithic Application을 배포하는 것은 일반적으로 하나의 대용량 Application을 여러 개의 동일한 복사본으로 실행한다는 것을 의미한다. 일반적으로 N개의 서버(실제 혹은 가상)를 준비하고, 각 서버마다 M개의 Application 인스턴스를 실행한다. Monolithic Application 배포는 항상 전적으로 쉽지는 않지만, Microservice Application을 배포하는 것보다는 훨씬 간단하다.

Microservice Application은 수십 혹은 수백개의 서비스로 이루어진다. 서비스는 다양한 언어와 프레임워크로 작성된다. 각각의 서비스는 그 자체적인 배포, 리소스, 확장, 모니터링 요구사항을 가진 작은 응용프로그램(mini-application)이다. 예를 들어, 각 서비스에 대한 수요 기반으로 특정 개수의 서비스 인스턴스를 실행할 필요가 있다. 각 서비스 인스턴스는 적당한 CPU, Memory, I/O 리소스를 제공받아야 한다. 더 까다로운 것은 이러한 복잡성에도 불구하고, 서비스들의 배포는 빠르고, 안정적이고, 비용 효율적이어야 한다는 것이다.

몇 가지 다른 Microservice 배포 패턴이 있다. 먼저, Host별 다중 서비스 인스턴스 패턴(Multiple Service Instance per Host pattern)에 대해서 살펴보자.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/777


Summary
(요약)

Microservice Architecture에서는 각 마이크로서비스가 자체적으로 데이터 저장소를 가지고 있다. 다른 Microservice들은 서로 다른 SQL 및 NoSQL 데이터베이스를 사용할 수 있다. 이러한 데이터베이스 아키텍처는 상당한 장점이 있지만, 분산 데이터를 다루는데 있어서 관리 문제가 발생한다. 첫번째 과제는 여러 서비스들 간에 데이터 일관성을 유지하는 비즈니스 트랜잭션을 어덯게 구현하느냐는 것이다. 두번째 과제는 여러 서비스에서 데이터를 검색하는 쿼리를 어떻게 구현하는가이다.

많은 Application에서 해결책은 Event-Driven Architecture를 사용하는 것이다. Event-Driven Architecture를 구현하는데 있어서 한 가지 문제는 상태를 원자적으로 업데이트하고 이벤트를 게시하는 것이다. 데이터베이스를 메시지 큐로 이용하는 방법, 트랜잭션 로그 마이닝으로 이용하는 방법, 이벤트 소싱으로 이용하는 방법등을 포함하여 몇 가지 방법이 있다.

앞으로의 블로그 글에서는 Microservice의 다른 측면에 대해서도 깊이 들여다 볼 것이다.
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/776


Achieving Atomicity
(원자성 달성)

Event-Driven Architecture에서는 데이터베이스를 원자적으로 업데이트하고 이벤트를 게시하는 문제가 있다. 예를 들면, Order Service는 ORDER 테이블에 행을 입력하고, Order Created Event를 게시해야 한다. 이 두가지 작업들은 원자적으로 수행되는 것이 필수적이다. 만약에 데이터베이스를 업데이트하고 이벤트를 게시하기 전에 서비스가 충돌하면 시스템은 데이터 일관성을 잃게 된다. 원자성을 보장하는 표준적인 방법은 데이터베이스와 Message Broker가 분산 트랜잭션을 사용하는 것이다.
그러나, 위에서 언급된 CAP이론과 같은 이유들 때문에 이것은 우리가 정확히 원하지 않는 것이다.

Publishing Events Using Local Transactions
(로컬 트랜잭션을 사용한 이벤트 게시)

원자성을 달성하는 한가지 방법은 Application이 로컬 트랜잭션만을 포함하는 Multi-step process를 사용하여 이벤트를 게시하는 것이다. 트릭은 Business Entity의 상태를 저장하는 데이터베이스에 Message Queue로서의 기능을 갖는 EVENT 테이블을 가지는 것이다. Application은 (로컬) 데이터베이스 트랜잭션을 시작하고, Business Entity의 상태를 업데이트한다. 그리고 이벤트를 EVENT 테이블에 입력하고, 트랜잭션을 커밋한다. 별도로 분리된 Application이나 Process가 EVENT 테이블에 질의하여 Message Broker에 이벤트를 게시하고, 이벤트가 게시되었음을 표시하기 위해 로컬 트랜잭션을 사용한다. 다음 다이어그램은 디자인을 보여 준다.

사용자 삽입 이미지


Order Service는 ORDER 테이블에 행을 삽입하고, EVENT 테이블에 Order Created 이벤트를 삽입한다. Event Publisher Thread나 Process는 게시되지 않은 이벤트에 대해 EVENT 테이블에 질의하고, 이벤트를 게시하고 나서 이벤트가 게시되었음을 표시하기 위해 EVENT 테이블을 업데이트한다.

이러한 접근 방법은 몇 가지 장점과 단점이 있다. 한가지 이점은 2PC에 의존하지 않고 각각의 업데이트에 대해 이벤트가 게시되는 것을 보장한다는 것이다. 또한, Application은 Business Level 이벤트를 게시하므로 추론할 필요가 없다. 이 접근법의 한가지 단점은 개발자가 이벤트 게시를 기억해야 하므로 잠재적으로 오류가 발생하기 쉽다. 이 접근법의 한계는 일부 NoSQL 데이터베이스를 사용하는 할 때, 제한된 트랜잭션과 쿼리 기능으로 인해 구현이 어렵다는 것이다.

이 접근법은 Application이 상태와 이벤트 게시를 업데이트 하기 위해 로컬 트랜잭션을 사용함으로써 2PC 필요성을 없애준다. 이제 Application이 간단히 상태를 업데이트하도록 함으로써 원자성을 달성하는 접근법에 대해 살펴보자.

Mining a Database Transaction Log
(데이터베이스 트랜잭션 로그 마이닝)

2PC없이 원자성을 달성하는 또다른 방법은 데이터베이스의 트랜잭션이나 커밋 로그를 조사하는 Thread나 Process에서 이벤트를 게시하는 것이다. Application은 데이터베이스를 업데이트 하고, 변경된 결과는 데이터베이스 트랜잭션 로그에 기록된다. Transaction Log Miner Thread나 Process가 트랜잭션 로그를 읽어서 Message Broker에 이벤트를 게시한다. 다음 다이어그램은 디자인을 보여준다.

사용자 삽입 이미지


이러한 접근법의 한 예로, LinkedIn DataBus 오픈소스 프로젝트가 있다. DataBus는 Oracle의 트랜잭션 로그를 조사하고, 변화에 따른 이벤트를 게시한다. LinkedIn은 다양한 파생 데이터 저장소와 시스템의 기록이 일치하도록 하는데 DataBus를 사용한다.

또다른 예는 Managed NoSQL 데이터베이스인 AWS DynamoDB의 스트림 메커니즘이 있다. DynamoDB 스트림에는 지난 24시간동안 DynamoDB 테이블에서 아이템에 이루어진 변경 사항(생성, 변경, 삭제 작업)에 대한 수행 시간 순서가 포함되어 있다. Application은 스트림에서 이러한 변경 사항들을 읽을 수 있고, 예를 들어, 그 변경 사항들을 이벤트로 게시할 수 있다.

트랜잭션 로그 마이닝에는 여러 가지 장점과 단점이 있다. 한가지 장점은 2PC없이 각 업데이트에 대해 이벤트가 게시된다는 것이다. 트랜잭션 로그 마이닝은 또한 Application의 비즈니스 로직으로부터 이벤트 게시 부분을 분리함으로써 Application을 단순화 할 수도 있다. 주요 단점은 트랜잭션 로그의 형식이 각 데이터베이스에 따라 다르고, 심지어 데이터베이스 버전 간에 변경될 수도 있다는 것이다. 또한, 트랜잭션 로그에 기록되어 있는 low-level update에서 high-level business event를 리버스 엔지니어링하는 것이 어려울 수도 있다.

트랜잭션 로그 마이닝은 Application이 데이터베이스 업데이트 한가지만 하게 함으로써 2PC의 필요성을 없애준다. 그럼 이제 업데이트를 제거하고, 단지 이벤트에만 의존하는 다른 접근법에 대해서 살펴보자.

Using Event Sourcing
(이벤트 소싱 사용)

이벤트 소싱은 지속적인 비즈니스 엔터티에 근본적으로 다른, Event-Centric 접근방법을 사용하여 2PC없이 원자성을 달성한다. 엔터티의 현재 상태를 저장하는 대신, Application은 상태가 변화된 이벤트의 순서를 저장한다. Application은 이벤트를 재생함으로써 이벤트의 현재 상태를 재구성한다. 비즈니스 엔터티 상태가 변경될 때마다, 새로운 이벤트가 이벤트 리스트에 추가된다. 이벤트를 저장하는 것은 단일 작업이기 때문에 본질적으로 원자적이다.

이벤트 소싱이 어떻게 동작하는지를 보기 위해서 Order 엔터티를 예로 들어보라. 전통적인 접근방식에서는 각 주문은 ORDER 테이블의 행과 ORDER_LINE_ITEM 테이블의 행에 맵핑된다. 그러나, 이벤트 소싱을 사용할 때에는 Order Service는 상태 변경 이벤트 (Created, Approved, Shipped, Calcelled)의 형태로 Order를 저장한다. 각 이벤트는 Order의 상태를 재구성하는데 충분한 데이터를 포함하고 있다.

사용자 삽입 이미지

이벤트는 이벤트 데이터베이스인 Event Store에 지속적으로 저장된다. 저장소는 엔터티 이벤트들을 추가하고 검색할 수 있는 API를 가지고 있다. Event Store는 또한 이전에 설명한 아키텍처에서 Message Broker처럼 동작한다. Event Store는 서비스가 이벤트를 구독할 수 있도록 해주는 API를 제공한다. Event Store는 모든 관심있어하는 구독자들에게 모든 이벤트를 전달한다. Event Store는 Event-Driven Microservice Architecture의 백본(Backbone)이다.

Event Sourcing은 몇가지 장점을 가지고 있다. Event-Driven Architecture를 구현할 때, 주요 문제점들 중 하나를 해결하고 상태가 변경될 때마다 이벤트를 안정적으로 게시할 수 있다. 결과적으로, Microservice Architecture에서 데이터 일관성 문제를 해결한다. 또한, 도메인 객체가 아닌 이벤트를 지속적으로 저장하고 있기 때문에 객체-관계 임피던스(비율) 불일치 문제를 피할 수 있다. Event Sourcing은 또한 비즈니스 엔터티에 일어난 변경에 대해 100% 신뢰할 수 있는 감사 로그를 제공하고, 특정 시점의 엔터티 상태를 결정하는 임시적인 쿼리를 구현할 수 있다. Event Sourcing의 또다른 주요 장점은 비즈니스 로직이 이벤트를 교환하는 비즈니스 엔터티와 느슨하게 결합되어 있다는 것이다. 따라서, Monolithic Application을 Microservice Architecture로 쉽게 마이그레이션할 수 있다.

Event Sourcing은 몇가지 단점이 있다. 프로그래밍 스타일이 다르고, 익숙하지 않기 때문에 학습 곡선이 있다. 이벤트 저장소는 Primary Key(기본 키)로 비즈니스 엔터티를 직접 조회하는 경우만 지원한다. 쿼리를 구현하기 위해서는 Command Query Responsibility Segregation(CQRS:데이터를 변경하는 Command를 데이터를 읽어들이는 Query와 분리하는 아키텍처 패턴-CRUD중에서 Read와 실제 데이터를 변경하는 CUD를 분리하는 분산 환경에서 사용. 예를 들어 Read는 Cache를 사용하고, CUD가 일어나는 시점에 Cache를 업데이트 하는 방식이 이에 해당함)을 사용해야 한다. 따라서, Application은 결과적으로 일관된 데이터를 처리해야만 한다.



받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/775