[등장배경]
넷플릭스는 2007년 데이터베이스틔 손상으로 3일간 서비스 장애를 겪으며 단일 장애 지점에서 벗어나고자 하는 목표를 세운다. 기존 Legacy 시스템을 MSA로 전환하면서 운영/개발 상의 효율성을 높이는 방법을 사용하였다. 신뢰성 높고 수평 확장이 가능한 클라우드 내 분산 시스템으로 이전하면서 고가용성, 유연한 스케일링, 빠르고 쉬운 배포의 장점을 가진 MSA를 선택하였다.
넷플릭스는 기존 데이터 센터가 지닌 문제점과 한계점을 타파하기 위해, 모든 시스템을 AWS로 가져다 놓는 방법 대신 클라우드 네이티브 방식을 선택하여 모든 기술을 재구축하고, 운영 방식도 재구축하였다. 7년에 걸치는 대장정 이후, 서비스 가용성이 대폭 증가되는 효과를 거두었다.
[Monolithic to Microservice]
- Dockerize
- Monolithic 구조에서 Microservice 구조로 변경.
- MSA는 서비스를 작은 단위로 분리하면서 개발과 배포에 있어 복잡도를 줄이고, 변경에 따른 영향을 최소화한다는 장점을 가지고 있다. 하지만 서비스가 분리된만큼 여러 엔드 포인트를 관리해야 한다는 단점이 있고, 각 서비스의 API에서 공통으로 필요한 기능을 중복 개발해야하는 문제가 있다.
[Auto Scale-out]
MSA에서 중요한 요소 중 하나인 자동 확장은 특정 서비스에 대한 트래픽과 부하에 따라 인스턴스를 추가로 생성하거나 제거하는 것을 의미한다.서비스 단위로 자동 확장이 가능하기 때문에 시스템 자원 활용을 최적화할 수 있지만, 구현되기 위해서 고려해야 할 것들이 많다. ex) 동적으로 추가되는 인스턴스 정보들을 다른 서비스로 전달하는 방법, 신규로 추가된 인스턴스 간의 로드 밸런싱 처리 및 장애 대응 방법 등.
[Netflix OSS 핵심 컴포넌트]
[Spring Cloud Netflix]
Spring Cloud는 스프링 부트를 기반으로 MSA 구축(클라우드 환경)에 특화된 라이브러리들의 집합으로 안에 Eureka, Hystrix, Ribbon, Zuul 등 많은 넷플릭스 OSS가 통합되어 있다.
[Eureka]
[Eureka의 필요성]
- 기존 Monolithic의 시절에는 각 서비스를 관리하기 위해, 도메인, ip정보, 포트 정보 등을 모두 알고 관리해야하고, 서비스를 줄이거나 늘여야 하는 상황에서는 수동으로 작성/관리가 필요했다. MSA 구조에서도 서비스들은 동적으로 확장되고, 축소되기도 하는데 각 마이크로 서비스를 유레카에 등록하여 id 기반으로 엔드 포인트 탐색이 가능하게 되었다 .그로 인해 Eureka 서버(서비스 디스커버리 서버)가 인스턴스 상태를 동적으로 관리해주는 역할을 하게 되었다.
- Eureka는 AWS클라우드에서 middle-tier 서버의 로드 밸런싱과 fail-over를 위해 서비스를 찾는데 사용되는 REST 기반 서비스이다. Eureka는 Eureka Server 와, 자바 기반 클라이언트 구성 요소인 Eureka Client를 함께 제공한다. 클라이언트에는 기본 round-robin 로드 밸런싱을 수행하는 로드 밸런서가 내장되어 있다. Eureka의 로드밸런서는 트래픽, 리소스 사용, 오류 조건 등과 같은 여러 요소들을 기반으로 가중된 로드 밸런싱 역할을 수행하여 우수한 탄력성을 제공한다.
[Eureka의 작동 원리]
- Eureka는 서비스 목록을 자동으로 관리하는 역할을 한다. 서비스들은 기동할 때마다, Eureka에게 IP, 호스트 주소, 포트 정보등을 전송한다. Eureka서버는 일정 주기마다 heartbeat를 보내 서비스가 정상 작동하는지 확인한다. 인스턴스가 새로 실행될 때마다 자신의 정보를 서버에 동적으로 등록하기 때문에 운영자들이 서비스를 수평 확장할 때, ip정보에 대해 신경 쓸 필요가 없어졌다.(여기서 수평확장이란 부하가 걸린 서비스에 인스턴스를 늘려 처리량을 높이는 것을 의미한다.) 운영자들은 설정 파일에 Eureka 서버 정보만 입력하고, 서비스들은 다른 서비스를 호출할 때, Eureka 서버에 등록된 인스턴스를 조회하면 된다.
[Ribbon]
- 모놀리식 시스템은 하나로 뭉쳐져 있기 때문에, 거대한 부하 분산을 위해 L4스위치 같은 하드웨어 장비를 앞 단에 두고 트래픽을 여러 서버로 분산하였다. 이런 중앙 집중화된 방식은 로드 밸런서에 장애가 발생할 경우, 전체 서비스에 문제가 생길 위험을 동반한다. 게다가 동적으로 서버가 추가, 삭제되는 환경에서 하드웨어 장비로 대응하는 것에도 한계가 있기 마련이다.
- Netflix는 Netflix API서비스와 같은 수백 개의 정교한 서비스를 클라우드 기반의 엣지서비스를 통해 지원하고 있다. Rest기반 프로토콜은 이런 서비스 프로세스 간의 통신을 위한 선택이다. Ribbon은 유레카와 함께 사용되는 내부 클라이언트 로드 밸런서로 주로 middle-tier 서비스에 대한 로드 밸런싱 요청을 처리한다.
- Ribbon은 클라이언트 소프트웨어로 구현한 클라이언트 사이드 로드 밸런서(Client Side Load Balancer)로 트래픽을 분산/ 제어할 수 있다.(여기서 클라이언트는 pc나 모바일 단말기가 아닌 MSA에서 다른 서비스를 호출하는 클라이언트 서비스이다.) 예를 들어, 100개의 서비스가 있는 환경에서 트래픽 이슈로 서비스가 추가/삭제된다면, l4와 같은 하드웨어에서는 똑같은 대응을 해야한다. Ribbon은 소프트웨어 로드밸런싱 알고리즘과 Netflix Internal Web Service Framework를 구성하는 몇가지 요소를 제공한다. Ribbon은 정적 서버 리스트를 가지고 부하 분사능ㄹ 할 수도 있고, Eureka와 연동하여 동저긍로 리스트를 관리하면서 부하 분산을 할 수도 있다.
- 부하 분산 알고리즘
- Simple Round Robin : 순서대로 돌아가며 선택하는 알고리즘
- Weighted Response Time: 서버 응답 시간에 따라 선택하는 알고리즘
- Availability filtering: n번 연속 호출 실패 시 m초 동안 목록에서 제외하는 알고리즘
- Zone-aware RoundRobin, Random Load Balancing등 ...
[Zuul]
[API Gateway]
- MSA는 도메인 별로 하나 이상의 서버가 따로 존재하고, 데이터를 각각 저장한다. 따라서 MSA구조를 사용하면 한 서비스에 여러 개의 서버가 존재하기 때문에 클라이언트에서는 엔드 포인트에 대한 관리에 어려움을 겪기도 한다. 이 어려움을 해결하기 위해 MSA환경에서는 서비스에 대한 도메인을 하나로 통합할 수 있는 API 게이트웨이가 필요하다.
- API Gateway는 사용자 요청을 적절한 서비스로 프록시/라우팅 하는 MSA의 컴포넌트이다. API 게이트웨이를 이용하면 클라이언트가 각 서비스의 엔드포인트 대신 API 게이트웨이로 요청을 전달하여, 엔드포인트와 REST API를 통합적으로 관리할 수 있다. API 게이트웨이는 즉, 라우터와 reverse proxy 기능 뿐 아니라 엔드포인트 서버에서 공통으로 필요한 인증, 접근 제어 등 공통적인 부분도 구현이 가능하다.
[Netflix의 Zuul]
- Zuul은 Spring Cloud Netflix에 특화된 API 게이트웨이이다. Netflix의 스트리밍 응용 프로그램은 서로 연결되어있고, 복잡한 시스템을 구성하고 있으며 클라우드 내 분산 시스템으로 전환하면서 다양한 장치 유형을 지원하고 다양한 요청을 받기 위한 진입점이 필요하다. 이러한 수많은 디바이스와 웹 사이트로부터 온 요청이 넷플릭스 스트리밍 애플리케이션의 백엔드로 가기 전 거치는 앞문의 역할을 Zuul이 한다. Zuul은 최전방에서 클라이언트의 요청을 받아 적절한 서비스에 전달하고 결과를 다시 클라이언트에 보내는 엣지 서버의 역할을 한다.
- 사용자에게 Zuul만 노출하고, 다른 마이크로서비스의 종단점을 숨기는 이유는 뭘까? MSA환경은 앞서 말했듯 한 서비스에 여러 서버가 존재할 수 있기 때문에, 사용자에게 다수의 진입점이 생기고, 각 진입점에서 인증과 보안, 잘못된 요청등을 처리하면서 변경이 생길 가능성이 있다. 일부의 진입점에 변경이 생길 경우 전체가 영향을 받기 때문에 관리가 까다로워진다. 이 때, Zuul을 활용하여 도메인을 하나로 통합하고, 단일 진입점만 사용한다면 관리가 수월해질 수 있다.
[Zuul의 기능]
- Filter File Manager: 일정 주기(정해진 시간)마다 정해진 directory에서 groovy로 정의된 filter 파일을 가져온다.
- Zuul Filter Runner: Filter에 정의된 기능 실행
- 기본적으로 필터는 다른 필터들과 직접적으로 통신할 수 없다. 그래서 각각의 요청 별로 Request Contest를 공유(thread local처럼)하여 통신할 수 있다.
[Zuul의 사용법]
- Autehntication and Security: 클라이언트 요청 시, 각 리소스에 대한 인증 요구 사항을 식별하고, 이를 만족하지 않는 요청은 거부
- Insights and Monitoring: 다른 Netflix OSS 구성요소들을 함께 사용하여 의미있는 데이터 및 통계 제공
- Dynamic Routing: 필요에 따라 요청을 다른 클러스터로 동적 라우팅
- Stress Testing: 성능 측정을 위해 점차적으로 클러스터 트래픽을 증가시킴
- Load Shedding: 각 유형의 요청에 대해 용량을 할당하고, 초과하는 요청은 제한
- Static Response Handling: 클러스터에서 오는 응답을 대신하여 API게이트웨이에서 응답 처리.
- Canary Testing: 실험적인 코드가 담긴 앱을 사용하여 어떤 버그를 유발하는지 빠르게 확인.
- Multi-Region Resiliency: 중요한 도메인에 대한 ELB의 다중 영역 이중화 지원
[Zuul Filter의 동작 방식]
Zuul은 필터 기능을 제공하여서 사용자의 요청에 대해 각 리소스의 인증 요구 사항을 식별하고, 만족하지 않는 요청은 거부한다. 필터는 동적으로 동작하기 때문에 정책이 바뀌어도 별도의 배포없이 반영할 수 있다.Zuul Filter는 크게 pre filtters, routing filters, post filters, custom filters, error filters로 나눌 수 있다.
- Pre 필터는 라우팅 전에 실행되는 필터로 주로 인증, Origin Server 섭택, 디버그, 정보 로깅을 담당한다.
- Routing 필터는 요청에 대한 라우팅을 다루는 필터이다. Origin Server로 라우팅하는데, 이 단계에서 리본을 사용한다. Apache HttpClient를 사용하여 정해진 URL로 보낼 수 있고, Netflix Ribbon을 사용하여 동적으로 라우팅 할 수도 있다.
- Post 필터는 요청이 라우팅 된 이후 실행된다. Response에 HTTP header를 추가하거나, 응답속도, status, code등 응답에 대한 statistics와 metrics를 수집하는 역할을 한다.
- Error 필터는 다른 단계 중 오류가 발생했을 경우 실행되는 필터이다.
⇒ 요약하자면, 요청이 들어왔을 때, pre 필터를 실행하고, routing 필터에 의해 정해진 서버로 요청을 보내게 된다. 이후 서버에서 응답이 오면 post 필터를 실행시킨다.
[Hystrix]
- MSA환경에서도 특정 서비스에 과부화가 걸리거나 문제가 생겨 정상 작동하지 않을 경우, 전체 서비스에 장애를 전파하는 경우도 있다. 서킷 브레이커는 특정 서비스에 문제가 생겼을 때, 확산되지 않도록 차단해주는 기능을 의미한다. 서킷 브레이커는 Fallback기능도 수행한다. 폴 백은 정해진 시간 내에 호출이 실패하면 대신 동작하는 예외 처리 기능이다. 개발자가 폴백 메서드를 구현하여 시스템 장애로부터 유연하게 복구를 실행할 수 있다. 또한, 서킷 브레이커의 정보나 각 서버의 상태를 확인할 수 있는 모니터링 기능도 제공하여 로그를 중앙 집중형으로 관리하고, 검색할 수 있다.
- Hystrix 서버는 각 서비스의 오류 내용이나, 오류상태, 복구 상태등을 파악한다. API 호출 통계를 기반으로 상대 서비스에서 이상을 감지하는 순간 즉시 통신을 중단하고, 문제가 있는 서비스를 격리한다. 이후 문제가 해결될 때까지, 별도의 스레드에서 밀린 작업을 수행하거나 호출 수를 제한하는 역할을 한다. 정상 상태로 복구되면, 통신을 연결하여 다시 호출을 받는다.
- 더 자세히 설명하면 Hystrix는 대기 시간 허용 및 내결함성 논리를 추가하여 분산 서비스 간의 상호작용을 제어하는데 도움이 되는 라이브러리이다. Hystrix는 서비스 간 엑세스 지점을 격리하고 여러 서비스에서 계단식 오류를 방지하며 대체 옵션을 제공하여 시스템의 전반적인 복원력을 향상시킨다.
- 대량의 트래픽으로 인해 어떤 하나의 서비스가 지연되거나 장애가 생길 경우, 모든 서버에서 모든 자원이 몇 초 내에 포화상태가 될 수 있다. 네트워크를 통해 또는 클라이언트를 통해 도달하며 네트워크 요청이 발생할 수 있는 응용 프로그램의 모든 지점은 잠재적인 오류의 원인이 되며, 장애보다 더 나쁜 이러한 응용 프로그램은 서비스 간 대기 시간을 늘려 대기열, 스레드 및 기타 시스템 리소스 등 시스템 전체에서 더 많은 계단식 오류를 발생시킨다.
[Hystrix의 동작 방법]
- 어떤 특정 서비스에서의 응답이 지연되어 정의된 임계값을 넘어가면, 기다리는 대신 사용자가 정의한 폴백 메서드를 실행하여 응답값을 클라이언트에게 전달한다. 그리고 새롭게 들어오는 다음 요청은 장애가 난 서비스에 컨택하지 않고 정의된 fallback 메서드를 즉시 실행하며, 장애가 복구되면 hystrix는 모니터링하고 있다가 정상화된 서비스에 다시 연결시켜 준다.
[참고자료]
- 문성길. 『넷플릭스하다: 4차 산업혁명의 키워드, 넷플릭스』. 스리체어스, 2017.
- https://techblog.woowahan.com/2523/
- https://github.com/Netflix
- https://netflix.github.io/
- https://bravenamme.github.io/2020/07/21/msa-netflix/
- https://www.samsungsds.com/global/ko/support/insights/msa_and_netflix.html
- https://dzone.com/articles/microservices-journey-from-netflix-oss-to-istio-se
- https://meetup.toast.com/posts/201
- https://microservices.io/patterns/apigateway.html
- https://netflixtechblog.com/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee
- https://startces.tistory.com/m/87
- https://github.com/spring-petclinic/spring-petclinic-microservices
- https://coe.gitbook.io/guide/sidecar-pattern/springcloudnetflixsidecar
- https://www.slideshare.net/balladofgale/spring-camp-2018-11-spring-cloud-msa-1
- https://www.slideshare.net/balladofgale/spring-cloud-workshop
- https://medium.com/netflix-techblog
- https://www.segye.com/newsView/20160608003504
'그냥저냥' 카테고리의 다른 글
[AI]Model Context Protocol (6) | 2025.06.13 |
---|---|
인텔리제이 인코딩 오류 java: illegal character 해결(일일히 복사하기😢) (0) | 2023.12.26 |
Docker-compose.yml 작성 (0) | 2023.04.03 |
Java 설치 (1)JDK설치 (0) | 2022.07.18 |