https://medium.com/aws-in-plain-english/basics-of-aws-cloud-architecture-cf949129b824

 

Basics of AWS Cloud Architecture

Want to learn about AWS architecture diagrams, why you need the skill and how to design your first AWS architecture diagram, check this…

aws.plainenglish.io

 

기초적인 내용이 체계적으로 잘 정리되어 있다.

계층형 아키텍처

  • 목적
    • 선택의 폭을 넓히고 변화하는 요구사항과 외부 요인에  빠르게 적응할 수 있게 해준다.
    • 애플리케이션의 목적은 비즈니스 규칙이나 정책을 반영한 모델을 만들어서 사용자가 이러한 규칙과 정책을 편리하게 활용할 수 있게 한다. 행동은 상태를 바꾸는 주체이기때문에 상태가 아니라 행동을 중심으로 모델링 해야 한다.

 

  • 문제
    • 코드에 나쁜 습관들이 스며들기 쉽게 만들고 점점 더 변경하기 어렵게 만드는 허점들을 노출한다.
      • 데이터 베이스 주도 설계 유도
      • 영속성 계층을 토대로 만들어진다. 
      • ORM 프레임워크를 결합하면 비즈니스 규칙을 영속성 관점과 섞고 싶은 유혹을 쉽게 받는다
      • 영속성 계층과 도메인 계층 사이에 강한 결합이 생긴다. 
    • 지름길을 택하기 쉬워진다. 
      • 상위계층에 위치한 컴포넌트에 접근해야 한다면 간단하게 컴포넌트를 계층 아래로 내려 버리면 된다. 
      • 어떤 것을 할수 있는 선택지가 있다면 누군가는 반드시 그렇게 하기 마련이다.
    • 테스트하기 어려워진다.
      • 간단한 변경의 경우 도메인을 웹계층에 구현하게 된다. 이런경우 테스트를 구현하려면 웹 계층에서 영속성 계층을 모킹해야 한다. 
      • 테스트의 복잡도가 올라가게 된다.
    • 유스케이스를 숨긴다.
      • 도메인 로직이 여러계층에 흩어지기 쉽다.
      • 여러개의 유스케이스를 담당하는 아주 넓은 서비스가 만들어지기도 한다. 
    • 동시 작업이 어려워진다. 
      • 영속성 계층을 먼저 개발해야 하고 그 다음에 도메인 계층, 웹계층을 만들어야 한다.

클린 아키텍처

  • 설계가 비즈니스 규칙의 테스트를 용이하게 한다. 
  • 비즈니스 규칙은 프레임워크, 데이터베이스, UI 기술, 그 밖의 외부 애플리케이션이나 인터페이스로부터 독립적일 수 있다.
  • 도메인 코드는 바깥으로 향하는 어떤 의존성도 없어야 한다. 
  • 의존성 역전원칙을 이용하여 모든 의존성이 도메인 코드를 향해야 한다.
  • 코어에는 유스케이스에서 접근하는 도메인 엔티티들이 있다. 
  • 유스케이스는 흔히 서비스라고 부르던 것들이고 단일 책임을 갖기 위해 세분화 되어야 한다. (넓은 서비스 문제 해결)
  • 도메인 계층이 영속성이나 UI 같은 외부 계층과 철저하게 분리 돼야 하므로 애플리케이션의 엔티티에 대한 모델을 각 계층에서 유지보수 해야 한다. 
  • 도매인 계층과 영속성 계층이 데이터를 주고 받을때 두 엔티티를 서로 변환해야 한다. 도메인 계층과 다른 계층들 사이에서도 마찬가지다.

헥사고날 아키텍처(포트와 어댑터 아키텍처)

  • 클린 아키텍처의 원칙을 조금 더 구체적으로 만들어 준다.
  • 웹어댑터, 외부 시스템 어댑터 -> 입력포트(인터페이스) <- 유스케이스 -> 엔티티 <- 유스케이스 -> 출력포트(인터페이스) <- 영속성 어댑터, 외부시스템 어댑터 
  • 도메인 중심 아키텍처에 적합

아키텍처적으로 표현력 있는 패키지 구조

business

L sub business

    L adapter

        L in

            L web - controller

        L out

            L persistent adapter

            L repository

     L domain - entity

     L application

         L port

            L in - usecase

            L out

  • 이 패키지 구조는 아키텍처-코드 갭 혹은 모델-코드 갭을 효과적으로 다룰 수 있는 강력한 요소다
  • 패키지 구조가 아키텍처를 반영할 수 없다면 시간이 지남에 따라 코드는 점점 목표하던 아키텍처로부터 멀어지게 될 것이다 
  • 패키지 내의 클래스들은 특성에 따라 접근제어자를 이용하여 계층간의 우발적인 의존성을 막을 수 있다. 
  • domain 패키지 내에서는 DDD가 제공하는 모든 도구를 이용해 우리가 원하는 어떤 도메인 모델이든 만들 수 있다. 
  • 아키텍처-코드갭을 넓히고 아키텍처를 반영하지 않는 패키지를 만들어야 하는 경우도 생길 수 있다. 

도메인 모델 구현하기

  • 도메인에 관련된 주요 기능을 포함하는 엔티티 구현
  • 비즈니스 규칙 유효성 검증
  • rich domain model
    • 엔티티에서 가능한 한 많은 도메인 로직 구현
    • 상태 변경 메소드 제공
    • 비즈니스 규칙에 맞는 유효한 변경만 허용
    • 유스케이스는 사용자의 의도만 표현
  • anemic domain model 
    • 도메인 로직을 가지지 않음
    • 엔티티 상태를 표현하는 필드와 getter, setter 메서드만 포함
    • 도메인 로직은 유스케이스에 구현

 

유스케이스 구현하기

  • 하는일
    • 입력을 받는다
    • 비즈니스 규칙을 검증한다.
    • 모델 상태를 조작한다
    • 출력을 반환한다
  • 입력 유효성 검증
    • 구문상(syntatical)의 유효성 검증
    • 이로인해 유스케이스가 오염 되지 않아야 함
    • 애플리케이션 계층의 책임
    • 입력모델이 다루기(anti corruption layer) 
    • Bean validation API 사용하기
    • 입력모델 생성자에서 validation 하기
  • 비즈니스 규칙 검증
    • 유스케이스의 맥락속에서 의미적인(semantical) 유효성 검증
    • 도메인 모델의 현재 상태에 접근
    • 도메인 엔티티 안에 구현
  • 출력 모델
    • 유스케이스에 맞게 구체적일 수록 좋음
    • 계속 질문하고 의심스럽다면 가능한 한 적게 반환하자
    • 단일 책임 원칙 적용
    • 도메인 엔티티를 출력모델로 사용하고 싶은 유혹을 견뎌내야 함

웹 어댑터 구현하기

  • 주도하는 / 인커밍 어댑터
  • 웹어댑터에서 애플리케이션 서비스로 제어흐름
  • HTTP와 관련된 것은 애플리케이션 계층으로 침투해서는 안됨
    • 다른 인커밍 어댑터의 요청에 대해 동일한 도메인 로직을 수행할 수 있는 선택지
    • 좋은 아키텍처에서는 선택의 여지를 남겨둔다
  • 의존성 역전원칙
    • 포트 인터페이스를 통해 서비스 호출
    • 포트 : 애플리케이션 코어가 외부세계와 통신할 수 있는 곳에 대한 명세
  • 책임
    • HTTP 요청을 자바 객체로 매핑
    • 권한검사
    • 입력유효성 검증
    • 입력을 유스케이스의 입력 모델로 매핑
    • 유스케이스 호출
    • 유스케이스의 출력을 HTTP로 매핑
    • HTTP 응답 반환
  • 콘트롤러 나누기
    • 가능한한 좁고 다른 컨트롤러와 적게 공유하는 웹 어댑터 조각 구현
    • 클래스마다 코드는 적을 수록 좋다
    • 모든 연산을 단일 콘트롤러에 넣는 것은 데이터 구조의 재활용을 촉진하게 됨
    • 메서드와 클래스명은 유스케이스를 최대한 반영해서 지어야 함
    • 콘트롤러자체의 모델을 갖거나 원시값을 받도록 함
    • 서로다른 연산에 대한 동시 작업이 쉬워짐
    • 병합충돌이 일어나지 않게됨
    • 더 파악하기 쉽고, 테스트하기 쉽다

영속성 어댑터 구현하기

  • 주도되는 / 아웃고잉 어댑터
  • 애플리케이션에 의해 호출되고 호출하지는 않음
  • 포트 인터페이스를 통해 통신
  • 책임
    • 입력을 받는다 (입력모델)
    • 입력을 데이터베이스 포맷으로 매핑한다 (JPA 엔티티)
    • 입력을 데이터베이스로 보낸다
    • 데이터베이스 출력을 애플리케이션 포맷으로 매핑한다
    • 출력을 반환한다
  • 포트 인터페이스 나누기
    • 인터페이스 분리 원칙
    • 클라이언트가 오로지 자신이 필요로 하는 메서드만 알면 되도록 넓은 인터페이스를 특화된 인터페이스로 분리
    • 매우 좁은 포트를 만드는 것은 프러그 앤드 플레이 경험으로 만든다
  • 연속성 어댑터 나누기
    • 애그리거트 하나당 하나의 영속성 어댑터 구현
      • 영속성 기능을 이용하는 도메인 경계를 따라 자동으로 나눠짐
      • 여러개의 바운디드 컨텍스트의 영속성 요구사항을 분리하기 위한 토대
    • 여러 종류의 어댑터 구현(JPA, native sql , ..)
  • 트랜잭션 
    • 영속성 어댑터를 호출하는 서비스에 위임

경계간 매핑하기

  • 매핑하지 않기(No mapping) 전략
    • 도메인과 애플리케이션 계층은 웹이나 영속성과 관련된 특수한 요구사항에 관심이 없지만 다루게 된다. 
    • 단일 책임 원칙 위반
    • 도메인 모델에 특정 커스텀 필드를 두도록 요구할 수 있다. 파편화된 도메인 모델
    • 모든 계층이 정확히 같은 구조의, 같은 정보를 필요하다면 완벽한 선택지 
  • 양방향(Two way) 매핑 전략
    • 각 계층이 전용모델를 가지고 있어 다른 계층에는 영향이 없다
    • 깨끗한 도메인 모델
    • 단일 책임 원칙 만족
    • 매핑 책임이 명확
    • 너무 많은 보일러 플레이트 코드 발생
    • 도메인 모델이 경계를 넘어서 통신하는데 사용. 바깥쪽 계층의 요구에 따른 변경에 취약
  • 완전(Full) 매핑 전략
    • 각 연산마다 별도의 입출력 모델 사용
    • 전역 패턴으로 추천하지 않음
    • 웹계층과 애플리케이션 계층사이에서 상태 변경 유스케이스의 경계를 명확하게 할때 가장 빛을 발한다. 
  • 단방향(One way) 매핑 전략
    • 모든 계층의 모델들이 같은 인터페이스를 구현
    • 특성에 대한 getter 메소드를 제공해서 도메인 모델의 상태를 캡슐화
    • 한 계층이 다른 계층으로부터 객체를 받으면 해당 계층에서 이용할 수 있도록 무언가로 매핑
    • 계층간의 모델이 비슷할때 가장 효과적
  • 언제 어떤 전략을 사용할 것인가?
    • 그때그때 다르다
    • 특정 작업에 최선의 패턴이 아님에도 깔끔하게 느껴진다는 이유로 선택해버리는것은 무책임한 처사다
    • 어제는 최선이었던 전략이 오늘은 아닐수도 있다
    • 빠르게 코드를 짤 수 있는 간단한 전략으로 시작해서 계층 간 결합을 떼어내는 데 도움이 되는 복잡한 전략으로 갈아타기
    • 어떤 상황에서 어떤 전략을 택해야 할지 가이드라인을 정해둬야 한다

아키텍처 경계 강제하기

  • 계층 경계를 넘는 의존성은 항상 안쪽 방향으로 향해야 한다.
  • 접근 제한자
    • package-private(default)
    • 자바 패키지를 통해 응집적인 모듈로 만들어 줌
    • 모듈의 진입점으로 활용될 클래스들만 public으로 만듬
    • 몇 개 정도의 클래스로만 이뤄진 작은 모듈에서 가장 효과적
  • 컴파일 후 체크
    • ArchUnit
    • 의존성 규칙 위반을 발견하면 예외
    • 패키지 사이의 의존성 방향이 올바른지 자동으로 체크
    • 실패에 안전하지는 않다
      • 오타의 경우 
      • 패키지명 리팩토링
      • 클래스를 하나도 찾지 못했을때 실패하는 테스트 추가 필요
    • 언제나 코드와 함께 유지 보수
  • 빌드 아티팩트
    • 모듈과 아키텍처의 계층 간의 의존성을 강제
    • 순환의존성 체크
    • 다른 모듈을 고려하지 않고 특정 모듈의 코드를 격리한채로 변경할 수 있음
    • 새로 의존성을 추가하는 일이 우연이 아닌 의식적인 행동이 됨
    • 빌드 스크립트 유지보수 비용

의식적으로 지름길 사용하기

  • 유스케이스간 모델 공유하기
  • 도메인 엔티티를 입출력 모델로 사용하기
  • 인커밍 포트 건너뛰기
  • 애플리케이션 서비스 건너뛰기

 

 

                                  

 

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

  • 적절한 마이크로서비스 경계 설정
    • 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/일급_객체

수정중....
5.1 웹서비스 프레임워크
  - 표준체계로 정의 되고 기술플랫폼으로 구현되어 추상화 수준이 높은형태로 존재
  - 웹서비스, 서비스 명세, 메시지를 포함하는 핵심구축단위
  - 커뮤니케이션 규약은 WSDL 기반의 서비스 명세 중심
  - 메시지 프레임워크는 SOAP의 기술과 개념으로 구성
  - 서비스 명세의 등록과 발견 아키텍처는 때때로 UDDI를 통해 구현
  - 메시징 패턴과 조합을 지원하는 잘정의된 아키텍처 존재

서비스의 로직 캡슐화방식 ------------------------> 웹서비스에서의 서비스
서비스간의 연결방식 -----------------------------> WSDL 서비스 명세
서비스간의 커뮤니케이션 방식 --------------------> SOAP 메시징

5.2 웹서비스에서의 서비스
5.2.1 서비스 역할
  - 서비스 제공자
  - 서비스 요청자 혹은 서비스 소비자
  - 중계자
5.2.2 서비스 모델
  - 비즈니스 서비스 모델
  - 유틸리티 서비스 모델
  - 컨트롤러 서비스 모델
5.3 WSDL 서비스 명세
5.3.1 서비스 엔트포인트와 서비스 명세
  - 추상명세
  - 실제명세
5.3.2 추상명세
  - 웹서비스 인터페이스 특징을 정의
  - 인터페이스(WSDL2.0) <- 포트타입(PORTTYPE) : 메시지를 분류하여 한 서비스가 오퍼레이션으로 알려진 기능의 그룸으로 처리될수 있다.
  - 오퍼레이션 : 서비스가 수행하는 특정기능
  - 메시지 : 파라미터
5.3.3 실제명세
  - 추상 웹서비스 인터페이스를 물리적인 전송 프로토콜에 연결
  - 바인딩 : 물리적인 연결을 수립하기 위한 서비스나 그 서비스를 수행하기 위한 연결에 필요한 것을 설명, 서비스 커뮤니케이션을 위해 사용, SOAP이 가장 일반적임
  - 포트 : 서비스가 어떤 특정 프로토콜로 접속할 때 물리적인 주소
  - 엔드포인트(WSDL2.0) <- 서비스 : 관련된 엔드포인트의 그룹
5.3.4 메타데이터와 서비스 제약
  - WSDL 정의
  - XSD 스키마
  - 정책
  - 서비스 계약 : 추가적인 문서나 서비스 명세에서 표현되지 않는 협약(SLA)
5.3.5 의미적 명세
5.3.6 서비스 명세 통지와 발견
  - 서비스 명세를 통지하고 발견하는 메커니즘 필요 - 중앙집중적인 디렉토리와 레지스트리
  - UDDI
  - 사설 레지스트리
  - 공용 레지스트리
5.4 SOAP 메시징

1.1 잘못된 soa
  soa = 웹서비스 ->soa의 이점을 누리려면 웹서비스 플랫폼에 투자하기만 하면된다..(X)

1.1.2 이상적인 soa
  - 일반적인 모델 - > 직무, 솔루션, 기업, 커뮤니티등에 동등하게 적용가능
  - 추상화레이어 - > 로직과 정보의 표준을 제시

1.1.3 실제 soa
  - 조직을 하향식으로 변환
  - 가이드 필수

3.1 SOA 기본
  - 서비스 지향 = 관심의 분리(SEPARATING CONCERN)

3.1.1 서비스 지향의 개념
  - 서비스 지향 + 아키텍쳐 = 기술적 의미의 SOA
  - SOA :자동화 로직이 작고 특정한 로직으로 분할할수있는 모델
  - SOA : 로직의 개별단위 들이 상호간에 서로 고립되지 않고 상호작용하면서도 자율적으로 존재해야함

3.1.2 서비스의 로직 캡슐화 방식
  - 전체 프로세스 -> 캡슐화된 서비스
  - 개별적인 서브 프로세스 -> 캡슐화된 서비스
  - 여러단계의 서브 프로세스 -> 캡슐화된 서비스

3.1.3 서비스 간의 연결 방식
  서비스A ------->서비스B에 대한 명세 ------------------------> 서비스B

3.1.4 서비스 간의 커뮤니케이션 방식
  - 메세지 : 커뮤니케이션이 독립적 단위 = 자율적 = 프로세스 로직의 일부를 스스로 통제할 수 있어야 함
3.1.5 서비스 설계 방식
  - 느슨한 결합(Loose coupling)
  - 서비스계약(Service Contract) : 서비스들은 커뮤니케이션에 동의해야하며, 하나 호은 그 이상의 서비스 명세와 관련 문서들로 정의된다.
  - 자율성
  - 추상화
  - 재사용성
  - 조합성
  - 무상태 유지(Stateless)
  - 발견성 : 명세를 기반으로 설계하므로 외부에서 쉽게 찾을 수 있고 서비스를 식별하는 메커니즘을 통해 접근할 수 있다
3.1.6 서비스 구축 방식
  - 웹 서비스
3.1.7 초기 SOA
  - 앞에서 말한 특성들을 만족하는 SOA
  - 아이디어에서 좀더 진보한 SOA
3.2 최신 SOA
  - 초기 SOA + 품질
  - 서비스 지향 컴퓨팅 플랫폼의 핵심
  - 서비스 품질향상
  - 자율성
  - 공개표준기반
  - 다양한 벤더지원
  - 서비스 발견성
  - 상호운영성
  - 통합용이성
  - 아키텍처 조합성
  - 재사용성
  - 확장성
  - 서비스지향 비즈니스 모델 지원
  - 추상화된 레이어 구현
  - 느슨한 결합관계
  - 조직적 기민성
  - 블록쌓기 방식의 구축
  - 진화의 산물
  - 계속되는 진화
  - 실현 가능한 아이디어
  - SOA 정의

최신 SOA는 공개, 기민성, 확장, 연합, 자립적 요소들로 구성된 조합가능한 아키텍처, 서비스품질, 다양한 벤터, 상호운영성, 서비스 발견 그리고 잠재적으로 재사용가능한 서비스들이 웹서비스로 구현된다.
SOA는 비즈니스 로직과 기술을 추상화 하여, 이 도메인간에 느슨한 결합을 유도한다.
SOA는 과거 플랫폼의 진화물로서, 전통적인 아키텍처의 특징들을 고스란히 가지고 있으며, 명확한 원칙을 가지고 SOE를 지원하며 서비스 지향을 촉진한다.
SOA는 엔터프라이즈 환경을 이상적으로는 표준화하지만, 치밀한 사전 계획에 의한 이전 필요성과 현재도 진화하고 있는 기술에 대한 지원만이 이러한 목적을 달성할 수 있다.


 

+ Recent posts