모놀리틱 아키텍쳐 (Monolithic architecture)
- HA(High Availability) 구성 : 지속적으로 구동되는(uptime) 시스템
- LoadBalancer : L4 switch(hardware), L7(Nginx, HAProxy)
- 콘웨이의 법칙(Conway’s Law) : 모든 조직은 조직의 의사소통 구조(communication structure)와 똑같은 구조를 갖는 시스템을 설계.
콘웨이의 법칙은 조직도에 초점을 두지 않고, 실질적인 소통관계에 관심을 둔다. 너무 많은 통신관계를 갖는 것은 프로젝트에 진정한 위험이 됨. - 장점 :
- 개발 단순 (repository 하나)
- 배포 단순 (war 하나)
- scale-out 이 단순( server 하나) 하지만, DB 성능으로 인한 한계
- 단점 :
- 무거움
- 어플리케이션 시작시간이 오래걸림
- 기술 스택 바꾸기 힘듬
- 높은 결합도
- 코드베이스의 책임 한계와 소유권이 불투명
마이크로서비스 아키텍쳐 (MSA; Micro Service Architecture)
- 시스템을 여러개의 독립된 서비스로 나눠서, 이 서비스를 조합함으로서 기능을 제공하는 아키텍쳐 디자인 패턴
- 각 서비스 간 network를 통해, 보통 HTTP를 통해 연동
- 독립된 배포 단위
- 각 서비스는 쉽게 교체 가능
- 각 서비스는 기능중심으로 구성됨 ex) 프론트엔드, 추천, 정산, 상품 등
- 각 서비스는 적합한 프로그래밍 언어, 데이터베이스, 환경으로 만들어진다.
- 서비스는 크기가 작고, 상황에 따라 경계를 정하고, 자율적으로 개발되고, 독립적으로 배포되고, 분산되고, 자동화 된 프로세스로 구축되고 배포된다.
Cloud Native
- 애플리케이션을 어떻게 만들고 배포하는지에 있으며, 위치는 중요하지 않다.
- 특징 : 신축성(Resiliency), 민첩성(Agility), 확장 가능성(Scalable), 자동화(Automation), 무상태(State-less)
Twelve-Factors
- Heroku 클라우드 플랫폼 창시자들이 정립한 애플리케이션 개발 원칙 중 유익한 것을 모아서 정리한 것
- 탄력적(elastic)하고, 이식성 있는(portability) 배포를 위한 베스트 프랙티스(Best Practices)
- 12가지 제약조건
1 코드베이스 단일 코드베이스. 버전 관리되는 하나의 코드베이스와 다양한 배포. 개발/테스트/ 운영서버(인스턴스)는 동일한 코드기반이어야 함 2 의존성 명시적으로 선언되고 분리된 의존성. 필요한 의존성을 애플리케이션과 함께 담음 3 설정 환경설정은 분리하여 외부에 보관. 소스코드(코드베이스)는 하나, 환경(개발/테스 트/운영)에 따라 설정만 바꿔야 함 4 백엔드 서비스 백엔드 서비스를 연결된 리소스로 취급. URL을 통해 접근(바인딩)되어야 함 5 빌드, 릴리즈, 실행 분리된 빌드와 실행 단계를 가져야 함 6 무상태 프로세스 애플리케이션을 하나 혹은 여러개의 무상태 프로세스로 실행. 상태는 외부저장소 에 보관 7 포트 바인딩 포트 바인딩을 사용해서 서비스 노출. 별도의 웹서버를 두지 않고 자기완결적으로 서비스 제공 8 동시성 프로세스 모델을 사용한 확장(scale out). 프로세스가 복제를 통해 확장될 수 있 게 설계해야 함 9 폐기 가능 빠른 시작과 그레이스풀 셧다운(graceful shutdown)을 통한 안정성 극대화 10 dev/prod 일치 development, staging, production 환경을 최대한 동일하게 유지 11 로그 로그를 이벤트 스트림으로 취급. 로컬서버에 저장하지 말고 중앙저장소로 수집 12 Admin 프로세스 admin/maintenance 작업을 일회성 프로세스로 실행
Netflix OSS, Spring Cloud
Netflix OSS, Spring Cloud의 교집합(Spring-Cloud-Netflix) : Hystrix, Eureka, Ribbon, Zuul
Hystrix – Circuit Breaker
- hystrix는 netflix에서 만든 라이브러리로 마이크로 서비스 아키텍처에서 분산된 서비스간 통신이 원활하지 않은 경우에 각 서비스가 장애 내성과 지연 내성을 갖게하도록 도와주는 라이브러리다.
- Latency Tolerance and Fault Tolerance for Distributed Systems
- Circuit Open? Circuit이 오픈된 Method는 (주어진 시간동안) 호출이 “제한”되며, “즉시” 에러를 반환한다.
- Why? 특정 메소드에서의 지연 (주로 외부 연동에서의 지연)이 시스템 전체의 Resource 를 (Thread, Memory등)를 모두 소모하여 시스템 전체의 장애를 유발한다. 특정 외부 시스템에서 계속 에러를 발생 시킨다면, 지속적인 호출이 에러 상황을 더 욱 악화 시킨다.
- So! 장애를 유발하는 (외부) 시스템에 대한 연동을 조기에 차단 (Fail Fast) 시킴으로서 나의 시스템을 보호한다.
- 기본설정 10초동안 20개 이상의 호출이 발생 했을때 50% 이상의 호출에서 에러가 발생하 면 Circuit Open
- Circuit이 오픈된 경우의 에러 처리는 ? – Fallback Fallback method는 Circuit이 오픈된 경우 혹은 Exception이 발생한 경우 대신 호출될 Method. 장애 발생시 Exception 대신 응답할 Default 구현을 넣는다.
- 오랫동안 응답이 없는 메소드에 대한 처리 방법은 ? – Timeout 설정하지 않으면 default 1,000ms 설정 시간동안 메소드가 끝나지 않으면 (return / exception) Hystrix는 메소드를 실제 실행중인 Thread에 interrupt() 를 호출 하고, 자신은 즉시 HystrixException 을 발생시킨다. 물론 이경우에도 Fallback이 있다면 Fallback을 수행
Server Side LoadBalancer
- hardware기반으로 비용 up, 유연성 down
- 서버를 추가하기 위해서는 설정 필요
- LoadBalancing Schema 이 한정적(Round Robbin, Sticky)
Client LoadBalancer – Ribbon
- software기반으로 비용 down, 유연성 up
- 서버를 추가하기 위해 변경이 자유로움(coding추가 필요)
- LoadBalancing Schema 이 마음대로 구성가능(coding추가 필요)
Dynamic Service Discovery – Eureka
- AWS와 같은 Cloud 시스템에서 서비스의 로드 밸런싱과 실패처리 등을 유연하게 가져가 위해 각 서비스들의 IP / Port / InstanceId를 가지고 있는 REST 기반의 미들웨어 서버
- Eureka in Spring Cloud 서버 시작 시 Eureka Server(Registry)에 자동으로 자신의 상태를 등록(up) : eureka.client.register-with-eureka : true(default) 주기적 HeartBeat으로 Eureka Server에 자신이 살아 있음을 알림 : eureka.instance.lease-renewal-interval-in-seconds: 30(default) 서버 종료 시 Eureka Server에 자신의 상태 변경(down) 혹은 자신의 목록 삭제 Eureka 상에 등록된 이름은 ‘spring.application.name‘
Declarative Http Client – Feign
- MSA 처럼 분산되어있는 시스템을 사용하는 입장에서는 API를 호출하는 코드를 노가다 식으로 항상 만들어줘야하는 번거로움이 생겼습니다. 이를 해결해 줄 수 있는 Spring Cloud 프로젝트가 바로 Feign입니다. Feign은 RestTemplate 호출 등을 JPA Repository 처럼 interface로 단순히 추상화 한 프로젝트입니다.
- Interface 선언을 통해 자동으로 Http Client를 생성
- RestTemplate 은 concreate 클래스라 테스트하기 어렵다
- Spring Cloud 에서 Open-Feign 기반으로 Wrapping 한 것이 Spring Cloud Feign
Zuul – API Gateway
- 모든 장비 또는 웹사이트에서 백엔드 서비스를 호출할 때 거치는 문 같은 역할을 하는 어플리케이션입니다. Edge 서비스 어플리케이션이라고도 하며 MSA에서 동적 라우팅, 모니터링, 보안 등을 담당
- API Gateway 클라이언트와 백엔드 서버 사이의 출입문(front door) 라우팅(라우팅, 필터링, API변환, 클라이언트 어댑터 API, 서비스 프록시) 횡단 관심사 cross-service concerns 보안. 인증(authentication) , 인가(authorization) 일정량 이상의 요청 제한(rate limiting) 계측(metering)
- Zuul의 모든 API 요청은 HystrixCommand로 구성되어 전달 각 API 경로 (서버군) 별로 Circuit Breaker 생성 하나의 서버군이 장애를 일으켜도 다른 서버군의 서비스에는 영향이 없다. CircuitBreaker / ThreadPool의 다양한 속성을 통해 서비스 별 속성에 맞는 설정 가능
- API를 전달할 서버의 목록을 갖고 Ribbon을 통해 Load-Balancing을 수행한다. 주어진 서버 목록들을 Round-Robin으로 호출 Coding을 통해 Load Balancing 방식 Customize 가능
- Eureka Client를 사용하여 주어진 URL의 호출을 전달할 “서버 리스트”를 찾는다. Zuul에는 Eureka Client가 내장 각 URL에 Mapping된 서비스 명을 찾아서 Eureka Server를 통해 목록을 조회 한다. 조회된 서버 목록을
Ribbon
클라이언트에게 전달한다. - Eureka + Ribbon에 의해서 결정된 Server 주소로 HTTP 요청 Apache Http Client가 기본 사용 OKHttp Client 사용 가능
- 선택된 첫 서버로의 호출이 실패할 경우 Ribbon에 의해서 자동으로 Retry 수행 Retry 수행 조건 Http Client에서 Exception 발생 (IOException) 설정된 HTTP 응답코드 반환 (ex 503)