마이크로서비스란?
다음 특징을 갖는 서비스들의 조합으로 이뤄진 설계
- 유지보수에 유리하고, 테스트 가능해야 함
- 느슨하게 결합되어야 함
- 독립적으로 배포 가능함
- 비즈니스 역량을 중심으로 구성해야 함
- 작은 팀에 의해 소유됨
서비스로서의 컴포넌트화
- 컴포넌트: 독립적으로 대체하거나 업그레이드 가능한 소프트웨어 단위
- 컴포넌트화: 시스템을 구성 요소(Component)를 나누고 이를 연결하여 구축하는 것
- 컴포넌트화는 어떻게?: 소프트웨어를 여러 서비스로 분리하는 것
비즈니스 수행에 따른 구성, 프로젝트가 아니라 제품
before: 기술적 계층에 따른 팀 분류
- 예) UI 팀, 비즈니스 로직 팀, 데이터베이스 팀
- 단순한 변경이 필요한 경우에도 팀 간의 협업 비용이 증가함
after: 비즈니스 수행 능력(업무 도메인)에 따른 팀 분류
- 도메인?
- 예) 쇼핑몰의 경우 회원/상품/배송이 각각의 도메인이 된다.
- 하나의 온전한 시스템의 단위
- 팀이 하는 일이 하나의 서비스로 나뉘어짐 → 마이크로서비스
- 이로 인한 장점으로는,
- 소프트웨어 스택, 데이터베이스 선택, 프로젝트 관리 등이 팀 별로 독립적이다.
- 이를 달성하기 위해서,
- 각 팀은 서비스에 대한 책임을 가져야 한다.
- 각 서비스는 메시지 버스(통신 인터페이스)를 통해 통신해야 한다.
- 이로 인한 장점으로는,
조직과 아키텍처의 연관성
시스템을 설계하는 조직은, 자신의 조직이 가진 커뮤니케이션 구조를 복제하는 아키텍쳐 디자인을 만들어 낸다. Mevlyn Conway, 1967
따라서 마이크로서비스로 소프트웨어를 작성할 때에는, 소프트웨어 작성에 앞서 팀의 일하는 방식을 보다 독립적으로 만들어내야 한다. 혹은 마이크로서비스 아키텍처를 통해, 팀의 일하는 방식이 보다 독립적으로 만들어질 수 있다. (Dev와 Ops가 함께 만들어가야 함)
현명한 엔드포인트와 바보 파이프라인
특징
다른 말로 표현하면 “서비스(엔드포인트)는 일을 하게 하고, 통신(파이프라인)은 최대한 단순하게 한다”
- 마이크로서비스에서의 프로세스간 통신은, “현명한 엔드포인트와 바보 파이프라인” 접근 방식을 따름
- 리눅스 파이프라인의 철학과 흡사
- 서비스와 서비스 사이는 느슨(decoupled)하게, 응집성은 높게
대표적인 방법
- REST API (HTTP)
- 메시지 버스를 이용한 메시지 전달 (메시지 큐)
분산화 거버넌스, 분산화된 데이터 관리
문제점
중앙 집중적인 시스템은 기술을 표준화하는 경향이 있음
“우리 회사는 Java 9와 Oracle만 사용합니다” “간단한 리포트 만드는 서비스가 필요한데, node.js로 금방하는 걸 Java를 꼭 써야해?”
문제 해결에 오히려 방해가 될 수 있음!
해결책
- 분산화된 시스템
- 소프트웨어 스택, 데이터베이스 선택, 프로젝트 관리 등이 팀 별로 독립적이다.
- 데이터에 대한 분산 책임이 따름
- 서비스 데이터베이스 간의 일관성이 중요 → 트랜잭션 협조가 중요
- 소프트웨어 스택, 데이터베이스 선택, 프로젝트 관리 등이 팀 별로 독립적이다.
- 분산화된 응용 프로그램 설계 → 도메인 주도 설계(DDD, Domain-Driven Design)
- 도메인 경계를 분명하게!
장애 방지 설계
(모놀리틱 설계에 비해 불리한 지점)
- 서비스는 언제든지 실패 할 가능성이 있음
- 신속하게 장애를 감지하고 가능하면 자동으로 서비스를 복구 할 수 있어야 함
- 예) 아키텍처 요소(데이터베이스가 받는 1초당 요청 수)와 비즈니스 관련(1초당 받는 주문 번호와 같은) 부분을 모두 확인
- 대시보드와 모니터링은 필수적임
진화하는 설계
- 컴포넌트 핵심: 컴포넌트가 개별적으로 대체 가능해야 하고, 업그레이드를 할 수 있어야 한다.
- 장점
- 모놀리스: 작은 변경 사항도 응용 프로그램 전체의 재배포를 필요로 합니다.
- 마이크로서비스: 변경한 서비스만 다시 배포하면 됩니다.
- 간단하고 신속한 출시 프로세스
- 단점
- 기존 서비스에 대한 변경이 이 서비스를 이용하고있는 다른 서비스에 영향을 주는지 여부를 신경써야 한다.
마이크로서비스 관련 질문
Q1 ) 마이크로서비스와 서버리스는 어떤 관계가 있나요?
FaaS.. 기능을 서비스로 사용한다.
서버리스 아키텍처와 FaaS(Functions-as-a-Service) 플랫폼이 마이크로서비스와의 유사성을 공유하는 점은, 이들이 모두 보다 작은 배치 단위를 작성하며 수요에 맞게 정확하게 스케일링하는 데 관심을 둔다는 점이다.
EC2같은 vm을 만들면 Scale 관리를 계속해줘야 한다.
AWS의 람다, 파게이트 같은 서비스를 사용하는 서버리스 방식을 사용하면 따로 관리할필요가없지만 함수를 깨우는데 기존 방식보다 시간적 제한사항이 있을 수 있다. 대신 기존의 IDC 서버는 열린 상태면 비용이 들지만 서버리스는 쓰는만큼의 비용이 장점으로 사이드 프로젝트나 마이크로서비스에 적합하다.
마이크로서비스 관리에 필요한 플랫폼을 스스로 구축하고 사용하는 어려움이 컸는데 서버리스는 그러한 것까지 클라우드 사업자(aws 등)가 대신해주는 방식으로 개발자가 마이크로서비스 개발에만 집중할 수 있도록 돕는다.
Q2) 서버리스의 특징 중 하나인 무상태성(Stateless)는 무엇을 의미하나요?
stateless 애플리케이션의 특징은 세션 상태와 관계 없이 요청에 대한 응답을 수행하는 인터넷 프로토콜에 적용할 수 있다. 대표적으로는 서버가 클라이언트의 상태를 저장하지 않는 UDP 프로토콜이 있다. 특히 서로 독립되어 동작하는 컨테이너 기반 애플리케이션에서도 서로의 상태에 영향을 미치지 않아야 하고 시작과 종료가 수시로 발생할 수 있다.
가장 좋은 방법은 Stateless 서비스를 설계하는 것일 수 있지만, 그럼에도 불구하고 State는 존재하며 서비스는 이를 인지해야 한다. 그리고 API 호출이 종종 해당 서비스의 상태를 초기에 설정하는 효과적인 방법이긴 하지만, 이는 최신 상태를 유지함에 있어서는 그리 효과적인 방법은 아니다. 서비스를 최신 상태로 유지하기 위해 AWTY(Are We There Yet?)를 지속적으로 폴링하는 접근 방법은 그다지 실용적이지 않다.
그 대신에, 서비스가 상태의 변화를 브로드캐스팅하고 다른 이해 당사자들이 해당 변경사항을 청취하고 적절하게 이를 조정할 수 있도록 상태 설정 API 호출을 메시징 또는 이벤트 스트리밍과 커플링하는 것이 필요하다.
이 작업은 범용 메시지 브로커에 가장 적합한 것 같지만, Apache Kafka 등의 이벤트 스트리밍 플랫폼이 적합한 경우도 존재한다.
그리하여 마이크로서비스와 Apache Kafka 같은 이벤트 기반 아키텍처를 결합함으로써 개발자는 대용량의 이벤트 또는 정보를 실시간으로 이용하고 처리할 수 있는 분산된, 고확장성의, 장애 허용 및 확장형 시스템을 구축할 수 있다.
실제로 배달의 민족의 경우 api 전달방식을 유지하다가 주문시스템의 주문상태를 리뷰나 라이더스에 뿌려주는데 만약에 리뷰시스템이 장애난다고하면 주문시스템도 영향받음. 장애대응의 관점에서 이를 이벤트 기반 전달방식으로 전환 (CQRS 아키텍쳐 및 AWS SNS 및 AWS SQS를 활용하여 주문시스템에 꼽는방식으로 개발)