마이크로서비스의 특징 : 확장성, 탄력성, 관리 편의성
🐵독립적인 소프트웨어 컴포넌트 != 정통적인 일체형 애플리케이션
고객이 플랫폼에서 사용하려는 기능 쉽게 찾아 선택할 수 있도록 각 기능은 독립적인 소프트웨어 컴포넌트로 개발 ==> 각 컴포넌트는 자체 데이터 저장소가 있었고, 다른 컴포넌트와는 명확한 API로 통신 (( 플랫폼은 고객의 요구 사항에 맞춰서 하나 혹은 여러 개의 서버에 배포할 수 있음))
플랫폼 기능을 독립적인 소프트웨어 컴포넌트로 나눴을 때의 장점
대부분의 문제점은 자체 개발 도구와 수동 처리를 위한 문서화된 지침으로 해결 가능.
처음에 일체형 애플리케이션으로 개발
-> 일체형 애플리케이션을 유지보수하고 개선 하는게 어려워짐 + 수직 스케일링(vertical scaling)의 한계 (== 가용한 최고 사양의 머신이 가진 성능을 넘어서 스케일링해야 한다는 난제 )
-> 스케일링할 수 있는 작은 컴포넌트로 나누는 방식으로 전환하기 시작
(cf. 앞단에 로드 밸런서를 배치하고 여러 개의 소형 서버에 작은 컴포넌트를 배포하면 수평 스케일링이 가능)
==> 결국 확장을 위해서 마이크로서비스를 선택
이를 위해 일체형 애플리케이션을 작은 컴포넌트로 나누는 것
마이크로서비스는 기본적으로 독자적인 업그레이드와 스케일링이 가능한 독립 소프트웨어 컴포넌트다.
디자인 패턴을 사용해 앞 절에서 설명한 마이크로서비스 문제를 완화하는 방법을 설명
(책 뒤에서는 스프링 부트, 스프링 클라우드, 쿠버네티스를 사용해 이런 디자인 패턴을 구현하는 방법 )
service discovery
실행되는 마이크로서비스 인스턴스는 시작하면서 동적 IP 주소를 할당 받는 게 일반적인데 클라이언트가 마이크로서비스와 그 인스턴스를 찾을 수 있어야 한다는 문제를 가지고 있다.
이를 해결하기 위해서 현재 사용 가능한 마이크로서비스와 그 인스턴스를 추적하는 새 컴포넌트(==서비스 검색)를 시스템 환경에 추가한다.
구현의 전략
1. 클라이언트 측 라우팅: 클라이언트는 '서비스 검색 서비스'와의 통신을 지원하는 라이브러리를 사용 -> 요청을 보낼 만한 인스턴스를 찾아 보냄
2. 서버 측 라우팅: 서비스 검색 서비스의 인프라는 모든 request을 전달하는 reverse proxy를 노출 -> 클라이언트를 대신해 적절한 마이크로서비스 인스턴스로 요청 전달
공개된 마이크로서비스는 악의적인 클라이언트의 요청으로부터 보호필요
일부 마이크로서비스만 시스템 환경 외부에 공개 + 그외는 외부 접근 못하게 숨겨야함
모든 요청이 거치는 시스템 환경에 새 컴포넌트(에지 서버)를 추가
( 일반적으로 에지 서버는 리버스 프록시로 동작, 동적 로드 밸런싱 기능 제공을 위해 검색 서비스와 통합 가능 )
블로킹 I/O(HTTP 기반의 RESTful JSON API와 같은) 를 사용하면 요청 처리 동안 운영체
제의 스레드를 점유 -> 운영체제의 가용 스레드가 부족해(b/c 동시 요청 수가 증가 또는 요청과 관련된 컴포넌트 증가시) 응답 시간이 늦어지거나 서버가 중단되는 문제
논블로킹 I/O를 사용해 db나 다른 마이크로서비스가 처리하길 기다리는 동안 스레드가 할당되는 것을 막음
다수의 마이크로서비스 인스턴스가 배포된 MSA 기반의 시스템 환경에서의 문제
1. 실행 중인 모든 마이크로서비스 인스턴스의 구성 정보를 한눈에 파악하는 방식 문제
2. 구성을 업데이트-> 관련된 모든 마이크로서비스 인스턴스가 올바르게 업데이트 시키는 방식 문제
시스템 환경에 모든 마이크로서비스의 구성 정보를 저장하는 새 컴포넌트(==구성 서버)를 추
가
마이크로서비스 집합에 대한 구성 정보를 한 곳에 저장하고 환경별(예: dev, test, qa, prod)
설정을 지원
로그를 중앙화해 관리
새 마이크로서비스 인스턴스를 감지해 로그 이벤트를 수집하고, 로그 이벤트를 해석해 구조적이고 검색 가능한 형식으로 중앙 db에 저장 하고, 그 이벤트를 조회 및 분석하기 위한 API와 그래픽 도구를 제공하는 새 컴포넌트 추가
시스템 환경에 대한 외부 호출 처리하는 동안 마이크로서비스 사이의 요청 및 메시지가 추적가능 해야함
관련된 모든 요청 및 메시지에 상관 ID를 넣어야 하고, 모든 로그 이벤트에 상관 ID 부여. (상관 id를 중앙화 로깅 서비스에 검색해서 로그 이벤트 서치)
1 모든 수신 요청과 이벤트에 고유 상관 ID를 할당
2 마이크로서비스에서 외부로 요청이나 메시지를 보낼 때는 요청과 메시지에 상관 ID를 넣어서 보내야함
3 모든 로그 이벤트에는 사전에 정의한 형식의 상관 ID가 있어야 함
동기 방식으로 상호 통신하는 마이크로서비스 시스템 환경은 연쇄 장애가 발생할 여지가 있음.
서킷 브레이커 추가 : 대상 서비스에 문제가 있다는 것을 감지 -> 새요청을 보내지 않도록 차단
중단되거나 지연된 마이크로서비스 인스턴스를 수동으로 감지하고 대처하는 것이 어려움 (다수 서비스가 여러 서버 분산된 시스템환경에서 )
제어루프를 시스템 환경에 추가 : 시스템 환경의 상태를 관찰
응답 시간이나 하드웨어 자원 사용량이 지나치게 높은 경우 문제의 근본 원인을 찾기 어려움
모니터 서비스 를 시스템 환경에 추가 : 마이크로서비스 인스턴스가 사용하는 하드웨어 자원 사용량에 대한 메트릭metric을 수집
1장에서는 마이크로서비스의 필수 개념과 장점 및 문제점을 소개했다. 마이크로서비스 기반 아키텍처와 문제 해결을 위한 디자인 패턴, 소프트웨어를 을 설명했다.
(정의)마이크로서비스는 기본적으로 독자적인 업그레이드와 스케일링이 가능한 독립 소프트웨어 컴포넌트다.
(목적)빠르게 개발해 지속적으로 배포하고 수동 혹은 자동으로 쉽게 스케일링하기 위해 일체형 애플리케이션을 작은 컴포넌트로 나눈다.
(조건) 마이크로서비스를 만들기 위해서는 독립적인 컴포넌트들이 아무것도 공유하지 않는 아키텍처를 유지 하고, 명확한 인터페이스를 통해서만 통신하고, 개별적인 런타임 프로세스로 배포하고, 각 인스턴스가 stateless여야 한다.
(문제) 마이크로서비스는 동기식 통신을 사용하는 다수의 소형 컴포넌트는 연쇄 장애 유발 가능하다는 문제와, 다수의 소형 컴포넌트를 최신 상태로 유지가 어렵고 컴포넌트 수준의 하드웨어 자원 사용량 분석 어렵다는 문제와, 많은 컴포넌트가 처리에 관여하는 요청은 추적이 어렵다는 문제 등이 있다. 이러한 문제들을 완화하는 방식으로 디자인패턴을 소개하고 있다.
(디자인패턴) 클라이언트가 마이크로서비스와 그 인스턴스를 찾을 수 있어야 한다는 문제를 해결하기 위한 '서비스 검색 ', 일부 마이크로서비스만 시스템 환경 외부에 공개 + 그외는 외부 접근 못하게 숨겨야한다는 문제를 해결하기 위한 '에지 서버', 운영체제의 가용 스레드가 부족해 응답 시간이 늦어지거나 서버가 중단되는 문제를 해결하기 위한 '리액티브 마이크로서비스' , 실행 중인 모든 마이크로서비스 인스턴스의 구성 정보를 한눈에 파악하는 방식과 구성을 업데이트-> 관련된 모든 마이크로서비스 인스턴스가 올바르게 업데이트 시키는 방식의 문제를 해결하기 위한 '구성 중앙화' , 전체 시스템 환경에서 발생하는 사건을 개괄하는 방법과 문제가 발생한 마이크로서비스 인스턴스를 찾아서 로그 파일에 오류 메시지 작성 방법, 최종 사용자가 문제 보고시 이와 관련 로그 메시지를 찾는 방법의 문제를 해결하기 위한 '로그 분석 중앙화' 시스템 환경에 대한 외부 호출 처리하는 동안 마이크로서비스 사이의 요청 및 메시지가 추적가능해야한다는 문제를 해결하기 위한 '분산 추적', 동기 방식으로 상호 통신하는 마이크로서비스 시스템 환경은 연쇄 장애가 발생할 여지가 있다는 문제를 해결하는 '서킷 브레이커', 중단되거나 지연된 마이크로서비스 인스턴스를 수동으로 감지하고 대처하는 것이 어렵다는 문제를 해결하는 '제어루프' , 응답 시간이나 하드웨어 자원 사용량이 지나치게 높은 경우 문제의 근본 원인을 찾기 어렵다는 문제를 해결하는 '모니터링 및 경고 중앙화' 의 패턴을 소개한다.