패턴 및 설계상의 일반적인 의사 결정

  • 적절한 마이크로서비스 경계 설정
    • DDD의 Bounded Context 개념
    • Bounded Context는 일반적으로 결합도가 낮으며, 때로는 아예 연결돼 있지 않기도 한다. 하나의 마이크로서비스에 대응 가능
    • 조직 구조도에 내재된 문제가 없다면 조직구조도에 따라 Bounded Context를 설정하는것이 현실적으로 가장 단순한 방법
    • 하향식 도메인 분해도 Bounded Context를 도출하는데 도움이 된다.
    • 마이크로서비스의 경계를 설계하는 가장 실용적인 방법은 가능한 여러가지 선택사항에 대해 서비스 리트머스 테스트를 했던 것처럼 손으로 시나리오를 돌려보는 것이다
      • 자율적인 기능 : 입력을 받아 내부의 로직과 데이터로 계산해서 결과를 반환
      • 암호화 엔진, 알림엔진 같은 유틸리티 기능이 적합
    • 배포단위의 크기 : 관리할 수 있는 수준 이내로 유지할 수 있어야 함
    • 분리하기에 가장 적합한 기능 또는 서브도메인
      • 자원소모량, 소유비용, 비즈니스 효용성, 유연성 등이 분석 기준
    • 폴리글랏 아키텍처
    • 선택적 확장 : 모든 기능 모듈이 모두 동일한 수준의 확장성을 필요로 하지는 않는다
      • 확장에 관한 요구사항을 기준으로 마이크로서비스의 경계를 결정
    • 작고 애자일한 팀
      • 전체 중에서 서로 다른 일부를 개발하는 데 집중할 수 있는 작고 집중력 있는 팀 구성을 통해 애자일 방식의 개발을 가능하게 해준다
    • 단일 책임
      • 책임을 비즈니스 범위 또는 하나의 기술 범위로 치환해서 생각하는 것이 더 현실적임
      • 하나의 마이크로서비스는 여러가지 책임을 담당해서는 안 된다
    • 복제가능성과 변경 가능성
      • 마이크로서비스가 전체 시스템에서 최소한의 재작성 비용 투입만으로 쉽게 떼어져 나올 수 있는지를 기준으로 식별돼야 한다.
    • 결합과 응집
      • 기능분해도는 의존관계트리와 함께 마이크로서비스의 경계를 수립하는데 도움을 줌
      • 트랜잭션 범위가 하나의 마이크로서비스의 범위를 넘어서 여러 마이크로서비스에 걸치지 않게 하는 것도 중요
      • 이벤트를 입력으로 받아 내부적으로 몇개의 함수를 호출하고 최종적으로 새로운이벤트를 반환하는 방식으로 반응하는 것이 기본
    • 마이크로서비스를 하나의 제품으로 생각하기
  • 통신 방식 설계
    • 먼저 요청-응답 동기방식으로 시작해서 나중에 필요하다고 판단될 때 비동기 방식으로 리팩터링
  • 마이크로서비스 조립(composability)
    • 오케스트레이션(orchestration) 방식과 연출(choreography)방식이 있음
    • 여러개의 서비스를 모아 하나의 완전한 기능을 만들고 오케스트레이터가 중앙의 두뇌 역할 담당
      • SOA에서는 ESB가 담당
    • 연출방식은 이벤트 생산자가 이벤트를 생상하고 소비자가 대기하고 있다가 소비하는 방식
    • MSA에서는 연출방식이 더 적합하지만 모든 사례에 연출방식으로 모델링하는 것은 불가능 함
  • 마이크로서비스 하나에 얼마나 많은 종단점을 둘 것인가?
    • 종단점의 수는 중요한 결정 사항이 아니다. 하나의 마이크로서비스는 하나 또는 그 이상의 종단점을 가질 수 있다. 마이크로서비스 크기에 적합하게 경계지어진 컨텍스트를 적절하게 설계하는 것이 훨씬 더 중요
  • 가상머신 하나당 하나의 마이크로서비스 또는 다수의 마이크로서비스?
    • 가상머신이 최대 사용치를 기준으로 두 걔의 서비스를 운영하기에 용량이 부족한가?
    • SLA를 충족시키기 위해 서비스들이 별도로 처리돼야 하는가?
    • 자원 요구사항이 서로 충돌되지는 않는가?
    • 3가지 질무에 No라고 답할 수 있다면 가능하지만 서비스들이 서로 어떤것도 공유하지 않으며, OS 프로세스와 독립적으로 실행된다는 점이 보장돼어야 함
  • 룰 엔진 공유 또는 내장?
    • 룰 엔진은 생산성을 높이고, 룰, 사실정보, 용어의 재사용을 가능하게 하며, rete알고리듬을 통해 룰을 더 빨리 실행할 수 있게 해준다
    • 룰이 단순하고 수적으로도 적고 서비스의 경계 내에서만 사용되며 룰 작성이 외부의 비즈니스 사용자에게 공개되지 않는다면 코딩하는것이 더 나을 수 있음
    • 룰이 복잡하고 서비스 컨텍스트에 국한되며 비즈니스 사용자에게 부여되지 않는다면 서비스 내부에 내장된 룰 엔진을 두는 편이 더 낫다
    • 룰이 비즈니스에 의해 작성되고 관리되거나, 룰이 복잡하거나, 룰이 서비스도메인 외부에서도 재사용된다면 외부에 있는 중앙저장소와 시스템 내부에 내장된 실행 엔진을 사용하는 것이 좋다
  • BPM의 역할과 작업흐름
    • 시스템과 사람의 상호작용을 자동화함으로써 전 구간의 여러기능에 걸쳐있는 비즈니스 프로세스를 모델링하는 상황에서 여러개의 마이크로서비스를 조합하는 상위 수준에서 사용가능
  • 마이크로서비스가 데이터 스토어를 공유할 수 있는가?
    • 공유데이터 모델, 공유 스키마, 공유테이블은 좋지 못한 방법이며, 마이크로서비스 개발을 재앙으로 이끌수도 있다
  • 서비스 종단점 설계 고려 사항
    • 계약설계
      • KISS(keep it simple stupid) : 더 나은 양질의 서비스를 더 빠르게 구축하고 유지 관리와 교체에 드는 비용을 줄여준다. YAGNI(you ain't Gonna need it). 단순함 중시
      • 소비자 중심 계약(Consumer Driven Contracts) : 사용자가 원하는 기대 사항을 서비스 제공자에게 테스트 케이스의 형태로 제공하게 함으로써 서비스 계약이 변경될 때마다 서비스 제공자가 통합테스트할 수 있게 해준다
    • 프로토콜 선택
      • 메시지지향서비스 : JMS/AMQP 프로토콜로 json 데이터 교환, 처리시간이 오래걸리는 작업에 적합
      • HTTP : 호환성, 프로토콜 처리, 트래픽 라우팅, 로드 밸런싱, 보안시스템등에 적합
      • REST : MSA 기본 선택 옵션, 
      • 최적화된 통신 프로토콜 : Avro, Protocol Buffers, Thrift 성능은 높이고 호환성은 떨어지게 됨
    • API 문서화 : Swagger, RAML, API Blueprint
  • 공유 라이브러리 처리
    • 자율성과 자기완비성 원칙을 준수하기 위해 코드와 라이브러리를 복제해야 하는 상황이 있을 수 있다
    • 비즈니스 범위나 분류관점에서 봤을때 하나의 마이크로서비스로 분류되지 않는 부분을 공통이라는 이유만으로 별도의 마이크로서비스로 떼어낸다면 효용보다 복잡성 증가라는 비용이 더 클 수도 있다
  • 마이크로서비스에서 API게이트웨이 사용
    • 서버는 화면까지 제공하기보다 RESTful서비스를 노출하는 방식으로 개발
    • 계약에 대한 기대사항의 불일치, 하나의 페이지를 렌더링하기 위해 서버에 여러번의 요청을 날리는 문제점이 있음
    • 해결방안
      • HATEOAS방식으로 최소한의 정보만을 링크정보와 함께 전달
      • 클라이언트가 요청 시 쿼리 문자열로 필요한 필드를 지정해서 요청
      • 간접화 개념 사용, 클라이언트와 서버 사이에 있는 게이트웨이 컴포넌트가 데이터 소비자의 명세에 따라 데이터를 변환
    • API 게이트웨이를 사용하는 목적에 따라 선택이 달라짐
      • 리버스 프록시 용도 : Apigee, Mashery 같은 서비스를 공유되는 플랫폼으로 사용
      • 트래픽 유형에 따른 세부적인 제어가 필요하고 복잡한 데이터 변환이 수반된다면 서비스당 독자저인 API게이트웨이 사용
  • ESB 및 iPass와 마이크로서비스의 사용
    • ESB의 역할
      • MSA에 적합하게 기능이 제한된 ESB역할은 API 게이트웨이로 대체
      • 오케스트레이션 역할은 ESB 버스에서 마이크로 서비스로 이동
      • 프로토콜 중재 역시 더 범용적인 메시지 교환 방식사용으로 필요하지 않음
      • 레거시 시스템과 연결해주는 어댑터 기능은 서비스 스스로가 구체적인 구현체를 제공하므로 필요 없음
      • 엔터프라이즈 수준에서 레거시와의 통합과 솔루션 회사의 애플리케이션을 통합하는데 존재 가치가 있음
  • 서비스 버저닝 고려사항
    • 시맨틱 버전이 널리 사용됨
      • 메이저, 마이너, 패치의 세가지 컴포넌트로 구성
      • 메이저 : 호환이 안될수도 있는 대규모 변경
      • 마이너 : 하위 호환을 유지하는 한도 내에서의 변경
      • 패치 : 버그수정
    • REST 버저닝 방식
      • URI 버저닝 : 대부분이 사용
      • 미디어 타입 버저닝
      • 커스텀 헤더
  • 크로스 오리진 설계
    • 마이크로서비스에서는 서비스가 동일한 호스트나 동일한 도메인에서 운영된다는 보장이 없음
    • 신뢰하는 다른 도메인으로부터의 크로스오리진 요청을 모든 마이크로서비스가 허용하게 하는 것
    • 클라이언트가 신뢰하는 도메인에 API 게이트웨이를 두는 것
  • 공유 참조 데이터 처리
    • 상대적으로 정적이고 변경될 가능성이 전혀 없는 데이터는 각 서비스에서 하드코드로 관리
    • 공통으로 사용되는 데이터를 별도의 마이크로서비스로 분리
    • 데이터를 모든 서비스에 복제
    • 필요한 데이터를 로컬에 캐시
  • 마이크로서비스와 대규모 데이터 작업
    • 데이터가 생성될때 사전 집계
    • 배치 API

 마이크로서비스의 과제

  • 데이터 섬
    • 마이크로서비스를 적용하면 데이터가 파편화돼 이질적인 데이터 섬으로 구성되는 상황을 맞이하게 됨
    • 데이터웨어하우스 : 배치성
    • 데이터 호수 : 하둡, NoSQL등을 이용한 준 실시간 처리
    • 데이터 호수의 경우 데이터의 사용목적을 가정하지 않고 그대로 저장
    • 데이터 전송 방안
      • 데이터 처리상황이 발생할 때 이벤트 발송
      • 스프링 데이터 플로우, kafka, flume등 사용
  • 로깅과 모니터링
  • 의존관계 관리
    • 서비스 경계를 적절하게 설정해서 의존성을 낮춰라
    • 의존성을 가능한 느슨하게 설계해서 변경에 의한 영향을 낮춰라. 또한 비동기 통신방식을 통해 서비스 간 상호작용이 일어나게 설계하라
    • 서킷 브레이커 같은 패턴을 사용해서 의존성 문제의 전파를 차단하라
    • 의존 관계 그래프 같은 시각화를 통해 의존 관계를 모니터링하라
  • 조직 문화
  • 관리체계문제
    • 분권화된 관리체계 필요
    • 더 나은 서비스를 만들기 위해 표준, 모범사례, 가이드라인 제정 필요
    • 모든 이해관계자가 개발된 모든 서비스를 보는 것 뿐 아니라, 모든 문서, 계약, 서비스 수준 합의도 볼 수 있어야 한다
  • 운영오버헤드
  • 마이크로서비스 테스팅
    • 서비스의 전 구간을 아우르는 동작을 평가하는 테스트는 어떻게 수행할 수 있을까?
      • 서비스 가상화 또는 목킹
      • 서비스 사용자 주도 계약
  • 인프라스트럭처 프로비저닝
마이크로서비스 역량 모델
  • 핵심역량
    • 서비스 리스너(HTTP 리스너/메시지 리스너)
    • 저장 기능
    • 비즈니스 범위 정의
    • 이벤트소싱
    • 서비스 종단점 및 통신 프로토콜
    • API 게이트웨이 : Zuul, Mastery, Apigee, 3scale
    • 사용자인터페이스
  • 지원역량
    • 소프트웨어 정의 로드 밸런서 : Ribbon, Eureka, Zuul
    • 중앙집중형 로그 관리
    • 서비스레지스트리 : Eureka, Zookeeper, Etcd
    • 보안서비스 : OAuth
    • 서비스 환경설정 : 스프링 클라우드 Config, Archaius
    • 테스팅 도구(anti-fragile, RUM) : netflix Simian Army
    • 모니터링 및 대시보드 : Turbine, Hystrix Dashboard, AppDynamic, New Relic, Dynatrace, said, Sense, Spigo
    • 의존 관계와 CI 관리 : CMDB
    • 데이터호수 : 스프링 데이터 플로우, Flume, Kafka, HDFS, Cassandra
  • 인프라스트럭처 역량
    • 클라우드
    • 컨테이너/가상머신
    • 클러스터 제어 및 프로비저닝 : Mesos, Kubernetes
    • 애플리케이션 라이프 사이클 관리 : Marathon
  • 프로세스 및 통제역량
    • 데브옵스
    • 데브옵스 도구
    • 마이크로서비스 저장소 : Nexsus, 도커레지스트리
    • 마이크로서비스 문서화 : Swagger, API Blueprint
    • 참조 아키텍처 및 라이브러리


마이크로 서비스로의 진화

- 기업은 소셜미디어, 모바일, 클라우드, 빅데이터, 사물인터넷드을 주요 수단으로 활용하며 시장에 빠르게 진입하기위한 방법에 관심을 갖게 되었으며, 그러한 것을 가능하게 하기위해 애자일성, 변경 및 배포 신속성, 확장성 같은 요소들에 관심을 갖게 되었다. 

- 기술적으로 다양한 관점에서 모든 계층의 구조를 다시 고려하게 하는 기술들이 개발 되었다. 프론트엔드의 Angular, Ember, Backbone등, 클라우드 환경의 AWS, 컨테이너 관련 Docker, 데이터베이스 영역에서는 NoSQL이 등장하였고  Hadoop, Cassandra, CochDB, Neo4j등이 있다.


마이크로서비스란 무엇인가?

- 물리적으로 분리할 수 있는 모듈화된 애플리케이션을 만들 수 있는 아키텍처 스타일이다.

- IT 시스템을 자율적이고, 자기 완비적(self-contained)이면서도 느슨하게 연결된 비즈니스 범위의 집합으로 만드는 아키텍처 스타일이다.

- 마이크로서비스 사이의 통신이나 전송방식에 정해진 표준은 없으나, 일반적으로 HTTP REST같은 경량프로토콜, AMQP같은 메시징 프로토콜을 주로 사용한다. 필요에 따라 Thrift, ZeroMQ, Protocol Buffers, Avro처럼 특수한 목적에 최적화된 통신프로토콜을 사용할 수도 있다.

- 마이크로서비스를 적용하기위해서 조직의 변화도 중요하다 기술에 대한 내재화, 개발과 운영의 간극을 좁히기 위한 DevOps같은 개념이 필연적이다


마이크로서비스의 원칙

- 서비스 하나에책임도 하나 : 클래스든 함수든 서비스든 간에 하나의 단위 요소는 반드시 하나의 책임만을 가져야 한다

- 마이크로 서비스는 자율적 : 자기 완비적이고, 독립적으로 배포할 수 있으며, 자율적인 서비스로서 비즈니스의 범위와 실행에 대해 전적인 책임을 진다.

- MSA 와 SOA의 차이점은 자율성 수준의 차이다. SOA는 서비스 수준의 추상화, MSA는 실행환경까지도 추상화


마이크로서비스의 특징

- 서비스는 일급 시민

- 서비스 계약

- 느슨한 결합

- 서비스 추상화

- 서비스 재사용

- 무상태

- 서비스 발견성

- 서비스 호환성

- 서비스 조립성

- 마이크로서비스는 경량

- 다양한 언어로 구성 가능

- 개발에서 배포까지 쉬운 자동화

- 마이크로서비스를 지원하는 생태계

- 동적이고 분산돼 있는 마이크로서비스

- 붕괴 저항성, 빨리 실패하기, 자체 치유


마이크로서비스의 장점

- 폴리글랏 아키텍처 지원 : 각 서비스는 자신만의 아키텍처와 여러가지 기술을 적용하여 구축 운영

- 실험과 혁신 유도

- 탄력적이고 선택적인 확장

- 대체 가능성

- 유기적 시스템 구축 유도 : 시간이 지남에 따라 점점 더 많은 기능을 추가하면서 성장해가는 시스템

- 기술적 부채 경감

- 다양한 버전의 공존

- 자기 조직화 시스템 구축 지원

- 이벤트 주도 아키텍처 지원

- 데브옵스 지원


다른 아키텍처 스타일과의 관계

SOA와의 관계 : SOA를 도입하는 방식에 따라 같기도 하고 다르기도 하다

- 서비스 지향 통합 : 다름

- 기존 시스템의 현행화 : 다름

- 서비스 지향 애플리케이션 : 마이크로서비스를 현재 도입한 SOA의 논리적인 다음 단계

12 요소 애플리케이션과의 관계

- 클라우드에서 운영 가능한 현대적인 애플리케이션에서 기대할 수 있는 특징을 기술하는 방법론

- 단일 코드 베이스 : 각 마이크로서비스는 자체적인 코드베이스를 가져야하고 다른 마이크로서비스와 공유되지 않는다(git/subversion)

- 의존성 꾸러미(bundling dependencies) : 모든 애플리케이션은 필요한 모든의존성을 애플리케이션과 함께 하나의 꾸러미에 담아야 한다(Maven/Gradle)

-  환경설정 외부화(externalizing configurations) 

- 후방 지원 서비스 접근성(backing service)

- 빌드, 출시, 운영의 격리

- 무상태, 비공유 프로세스

- 서비스를 포트에 바인딩해서 노출

- 확장을 위한 동시성 : 프로세스가 복제를 통해 확장될 수 있게 설계

- 폐기 영향 최소화(disposability with minimal overhead) : 애플리케이션의 시동과 종료에 필요한 시간을 최소화하고, 서버가 종료될때에는 필요한 처리가 모두 수행되어야 함(lazy loading)

- 개발과 운영의 짝 맞춤(Development and production parity) : 개발 환경과 운영 환경을 가능한 한 동일하게 유지

- 로그 외부화 : 로그파일을 절대로 자기 자신안에 담지 않는다. 중앙집중식 로깅 프레임워크사용(Splunk, Greylog, Logstash, Logplex, Loggly) 로그백 추가자를 통해 로그를 중앙 저장소에 적재하고, 적재 도구의 종단점에 로그를 쓰는 방법

- 패키지 관리자 프로세스 : 관리자 태스크를 위한 코드도 애플리케이션 코드와 함께 패키징되어야 한다.


마이크로서비스 사용 사례

- 일체형의 전환

- 넷플릭스, 우버, 에어비앤비, 오비츠, 이베이, 아마존, 길트, 트위터, 나이키


참고자료

- hexagonal architecture : http://alistair.cockburn.us/Hexagonal+architecture

- avro : http://avro.apache.org/docs/current/

- DevOps : http://dev2ops.org/2010/02/what-is-devops/

- 일급시민 : https://ko.wikipedia.org/wiki/일급_객체

+ Recent posts