편집자 – 이 7부작 시리즈 기사는 이제 완료되었습니다.
NGINX Plus를 사용하여 마이크로서비스를 구현하는 것에 대한 정보와 더불어 전체 문서 세트를 전자책으로 다운로드할 수도 있습니다. – 마이크로서비스: 설계부터 배포까지 . 또한 새로운 마이크로서비스 솔루션 페이지 를 확인해 보세요.
마이크로서비스를 설계, 구축, 배포하는 것에 대한 7부작 시리즈의 첫 번째 기사에서는 마이크로서비스 아키텍처 패턴을 소개했습니다. 마이크로서비스를 사용하는 것의 이점과 단점을 논의하였고, 마이크로서비스의 복잡성에도 불구하고 일반적으로 복잡한 애플리케이션에 이상적인 선택이라는 점을 설명했습니다. 이 기사는 이 시리즈의 두 번째 기사로, API 게이트웨이를 사용하여 마이크로서비스를 구축하는 방법에 대해 설명합니다.
애플리케이션을 마이크로서비스 세트로 빌드하기로 선택한 경우 애플리케이션의 클라이언트가 마이크로서비스와 어떻게 상호 작용할 것인지 결정해야 합니다. 모놀리식 애플리케이션에는 (일반적으로 복제되고 부하가 분산된) 엔드포인트 세트가 하나만 있습니다. 그러나 마이크로서비스 아키텍처에서는 각 마이크로서비스가 일반적으로 세분화된 엔드포인트 집합을 노출합니다. 이 문서에서는 이것이 클라이언트-애플리케이션 통신에 어떤 영향을 미치는지 살펴보고 API Gateway를 사용하는 접근 방식을 제안합니다.
쇼핑 애플리케이션을 위한 네이티브 모바일 클라이언트를 개발한다고 가정해 보겠습니다. 특정 제품에 대한 정보를 표시하는 제품 세부 정보 페이지를 구현해야 할 가능성이 높습니다.
예를 들어, 다음 다이어그램은 Amazon Android 모바일 애플리케이션에서 제품 세부 정보를 스크롤할 때 표시되는 내용을 보여줍니다.
스마트폰용 앱이긴 하지만, 제품 상세 페이지에는 많은 정보가 표시됩니다. 예를 들어, 기본적인 제품 정보(이름, 설명, 가격 등)뿐만 아니라 이 페이지에는 다음 내용도 표시됩니다.
모놀리식 애플리케이션 아키텍처를 사용하는 경우 모바일 클라이언트는 애플리케이션에 단일 REST 호출( GET
api.company.com/productdetails/productId
)을 수행하여 이 데이터를 검색합니다. 로드 밸런서는 요청을 N개의 동일한 애플리케이션 인스턴스 중 하나로 라우팅합니다. 그러면 애플리케이션은 다양한 데이터베이스 테이블에 쿼리를 보내고 클라이언트에 응답을 반환합니다.
반면, 마이크로서비스 아키텍처를 사용할 경우 제품 세부 정보 페이지에 표시되는 데이터는 여러 마이크로서비스가 소유합니다. 예시 제품 세부 정보 페이지에 표시된 데이터를 소유하는 잠재적인 마이크로서비스 중 일부는 다음과 같습니다.
모바일 클라이언트가 이러한 서비스에 어떻게 접근하는지 결정해야 합니다. 옵션을 살펴보죠.
이론상 클라이언트는 각 마이크로서비스에 직접 요청을 할 수 있습니다. 각 마이크로서비스에는 공개 엔드포인트( https:// serviceName .api.company.name )가 있습니다. 이 URL은 마이크로서비스의 로드 밸런서에 매핑되어 요청을 사용 가능한 인스턴스에 분산시킵니다. 제품 세부 정보를 검색하려면 모바일 클라이언트가 위에 나열된 각 서비스에 요청을 보내야 합니다.
안타깝게도 이 옵션에는 어려움과 한계가 있습니다. 한 가지 문제는 클라이언트의 요구 사항과 각 마이크로서비스에서 제공되는 세분화된 API 간의 불일치입니다. 이 예에서 클라이언트는 7개의 별도 요청을 해야 합니다. 더 복잡한 응용 프로그램에서는 훨씬 더 많은 것을 만들어야 할 수도 있습니다. 예를 들어, Amazon은 수백 개의 서비스가 제품 페이지를 렌더링하는 데 어떻게 사용되는지 설명합니다. 클라이언트가 LAN을 통해 그렇게 많은 요청을 할 수는 있겠지만, 공용 인터넷에서라면 너무 비효율적일 것이고 모바일 네트워크에서라면 확실히 비실용적일 것입니다. 이러한 접근 방식은 클라이언트 코드를 훨씬 더 복잡하게 만듭니다.
클라이언트가 마이크로서비스를 직접 호출하는 데에는 또 다른 문제가 있는데, 일부는 웹 친화적이지 않은 프로토콜을 사용할 수 있다는 것입니다. 한 서비스는 Thrift 바이너리 RPC를 사용하고, 다른 서비스는 AMQP 메시징 프로토콜을 사용할 수 있습니다. 두 프로토콜 모두 브라우저나 방화벽에 특별히 친화적이지 않으므로 내부적으로 사용하는 것이 가장 좋습니다. 애플리케이션은 방화벽 외부에서 HTTP 및 WebSocket과 같은 프로토콜을 사용해야 합니다.
이 접근 방식의 또 다른 단점은 마이크로서비스를 리팩토링하기 어렵다는 것입니다. 시간이 지남에 따라 시스템을 서비스로 분할하는 방식을 변경하고 싶을 수도 있습니다. 예를 들어, 두 개의 서비스를 병합하거나 하나의 서비스를 두 개 이상의 서비스로 분할할 수 있습니다. 그러나 클라이언트가 서비스와 직접 소통하는 경우 이러한 종류의 리팩토링을 수행하는 것은 매우 어려울 수 있습니다.
이런 종류의 문제 때문에 클라이언트가 마이크로서비스와 직접 통신하는 것은 거의 의미가 없습니다.
보통 훨씬 더 나은 방법은 API 게이트웨이 라고 알려진 것을 사용하는 것입니다. API 게이트웨이는 시스템에 대한 단일 진입점인 서버입니다. 이는 객체 지향 설계의 Facade 패턴과 유사합니다. API 게이트웨이는 내부 시스템 아키텍처를 캡슐화하고 각 클라이언트에 맞는 API를 제공합니다. 인증, 모니터링, 부하 분산, 캐싱, 요청 형성 및 관리, 정적 응답 처리와 같은 다른 책임이 있을 수도 있습니다.
다음 다이어그램은 API 게이트웨이가 일반적으로 아키텍처에 어떻게 적용되는지 보여줍니다.
API 게이트웨이는 요청 라우팅, 구성 및 프로토콜 변환을 담당합니다. 클라이언트의 모든 요청은 먼저 API 게이트웨이를 거칩니다. 그런 다음 요청을 적절한 마이크로서비스로 라우팅합니다. API 게이트웨이는 종종 여러 마이크로서비스를 호출하고 결과를 집계하여 요청을 처리합니다. HTTP 및 WebSocket과 같은 웹 프로토콜과 내부적으로 사용되는 웹에 비친화적인 프로토콜 간을 변환할 수 있습니다.
API Gateway는 또한 각 클라이언트에게 사용자 정의 API를 제공할 수 있습니다. 일반적으로 모바일 클라이언트를 위한 거친 API를 노출합니다. 예를 들어, 제품 세부 정보 시나리오를 생각해 보겠습니다. API 게이트웨이는 모바일 클라이언트가 단 한 번의 요청으로 모든 제품 세부 정보를 검색할 수 있는 엔드포인트( /productdetails?productid= xxx )를 제공할 수 있습니다. API 게이트웨이는 제품 정보, 추천, 리뷰 등 다양한 서비스를 호출하고 결과를 결합하여 요청을 처리합니다.
API 게이트웨이의 좋은 예로는 Netflix API 게이트웨이가 있습니다. Netflix 스트리밍 서비스는 TV, 셋톱박스, 스마트폰, 게임 시스템, 태블릿 등 수백 가지 종류의 기기에서 이용할 수 있습니다. 처음에 Netflix는 스트리밍 서비스에 단일 API를 제공하려고 시도했습니다. 그러나 그들은 다양한 기기와 기기의 고유한 요구 사항 때문에 이 방식이 잘 작동하지 않는다는 것을 발견했습니다. 오늘날에는 장치별 어댑터 코드를 실행하여 각 장치에 맞는 API를 제공하는 API 게이트웨이를 사용합니다. 일반적으로 어댑터는 평균 6~7개의 백엔드 서비스를 호출하여 각 요청을 처리합니다. Netflix API 게이트웨이는 하루에 수십억 개의 요청을 처리합니다.
예상할 수 있듯이 API 게이트웨이를 사용하는 데는 이점과 단점이 모두 있습니다. API 게이트웨이를 사용하는 가장 큰 이점은 애플리케이션의 내부 구조를 캡슐화한다는 것입니다. 특정 서비스를 호출하는 대신 클라이언트는 게이트웨이와 대화하기만 하면 됩니다. API 게이트웨이는 각 종류의 클라이언트에 특정 API를 제공합니다. 이를 통해 클라이언트와 애플리케이션 간의 왕복 횟수가 줄어듭니다. 또한 클라이언트 코드도 간소화됩니다.
API 게이트웨이에도 몇 가지 단점이 있습니다. 이는 개발, 배포, 관리해야 하는 또 다른 고가용성 구성 요소입니다. API 게이트웨이가 개발 병목 현상이 될 위험도 있습니다. 개발자는 각 마이크로서비스의 엔드포인트를 노출하기 위해 API 게이트웨이를 업데이트해야 합니다. API 게이트웨이 업데이트 프로세스는 가능한 한 가벼워야 합니다. 그렇지 않으면 개발자는 게이트웨이를 업데이트하기 위해 줄을 서서 기다려야 합니다. 하지만 이러한 단점에도 불구하고 대부분의 실제 애플리케이션에서는 API 게이트웨이를 사용하는 것이 합리적입니다.
이제 API 게이트웨이 사용의 동기와 장단점을 살펴보았으니, 고려해야 할 다양한 설계 문제를 살펴보겠습니다.
넷플릭스만큼 대규모로 운영되고 하루에 수십억 건의 요청을 처리해야 하는 회사는 극소수에 불과합니다. 그러나 대부분의 애플리케이션에 있어서 API 게이트웨이의 성능과 확장성은 보통 매우 중요합니다. 그러므로 비동기, 비차단 I/O를 지원하는 플랫폼에 API Gateway를 구축하는 것이 합리적입니다. 확장 가능한 API 게이트웨이를 구현하는 데 사용할 수 있는 다양한 기술이 있습니다. JVM에서는 Netty, Vertx, Spring Reactor, JBoss Undertow와 같은 NIO 기반 프레임워크 중 하나를 사용할 수 있습니다. 인기 있는 비 JVM 옵션 중 하나는 Chrome의 JavaScript 엔진을 기반으로 구축된 플랫폼인 Node.js입니다. 또 다른 옵션은 NGINX Plus를 사용하는 것입니다. NGINX Plus는 쉽게 배포, 구성 및 프로그래밍할 수 있는 성숙하고 확장 가능하며 고성능의 웹 서버와 역방향 프록시를 제공합니다. NGINX Plus는 인증, 액세스 제어, 부하 분산 요청, 캐싱 응답을 관리하고 애플리케이션 인식 상태 점검 및 모니터링을 제공합니다.
API 게이트웨이는 일부 요청을 적절한 백엔드 서비스로 라우팅하여 처리합니다. 여러 백엔드 서비스를 호출하고 결과를 집계하여 다른 요청을 처리합니다. 제품 세부 정보 요청 등 일부 요청의 경우 백엔드 서비스에 대한 요청은 서로 독립적입니다. 응답 시간을 최소화하기 위해 API 게이트웨이는 독립적인 요청을 동시에 수행해야 합니다. 그러나 때로는 요청 간에 종속성이 있는 경우가 있습니다. API 게이트웨이는 백엔드 서비스로 요청을 라우팅하기 전에 먼저 인증 서비스를 호출하여 요청을 검증해야 할 수도 있습니다. 마찬가지로, 고객의 위시리스트에 있는 제품에 대한 정보를 가져오려면 API 게이트웨이는 먼저 해당 정보가 포함된 고객 프로필을 검색한 다음, 각 제품에 대한 정보를 검색해야 합니다. API 구성의 또 다른 흥미로운 예는 Netflix 비디오 그리드 입니다.
기존의 비동기 콜백 방식을 사용하여 API 구성 코드를 작성하면 콜백 지옥에 빠르게 빠지게 됩니다. 코드는 복잡하고, 이해하기 어렵고, 오류가 발생하기 쉽습니다. 훨씬 더 나은 방법은 반응형 방식을 사용하여 선언적 스타일로 API Gateway 코드를 작성하는 것입니다. 반응형 추상화의 예로는 Scala의 Future , Java 8의 CompletableFuture , JavaScript의 Promise 등이 있습니다. 또한, Microsoft에서 .NET 플랫폼용으로 개발한 Reactive Extensions (Rx 또는 ReactiveX라고도 함)도 있습니다. Netflix는 API Gateway에서 사용하기 위해 JVM용 RxJava를 만들었습니다. 브라우저와 Node.js에서 모두 실행되는 JavaScript용 RxJS도 있습니다. 반응형 접근 방식을 사용하면 간단하면서도 효율적인 API Gateway 코드를 작성할 수 있습니다.
마이크로서비스 기반 애플리케이션은 분산 시스템이므로 프로세스 간 통신 메커니즘을 사용해야 합니다. 프로세스 간 통신에는 두 가지 스타일이 있습니다. 한 가지 옵션은 비동기 메시징 기반 메커니즘을 사용하는 것입니다. 일부 구현에서는 JMS나 AMQP와 같은 메시지 브로커를 사용합니다. Zeromq와 같은 다른 솔루션은 브로커가 없고 서비스 간 직접 통신이 가능합니다. 프로세스 간 통신의 다른 스타일은 HTTP나 Thrift와 같은 동기식 메커니즘입니다. 일반적으로 시스템은 비동기 및 동기 스타일을 모두 사용합니다. 각 스타일을 여러 개 구현할 수도 있습니다. 따라서 API 게이트웨이는 다양한 통신 메커니즘을 지원해야 합니다.
API 게이트웨이는 통신하는 각 마이크로서비스의 위치(IP 주소 및 포트)를 알아야 합니다. 기존 애플리케이션에서는 위치를 하드와이어링할 수 있겠지만, 최신 클라우드 기반 마이크로서비스 애플리케이션에서는 이는 간단한 문제가 아닙니다. 메시지 브로커와 같은 인프라 서비스는 일반적으로 정적 위치를 가지며, 이는 OS 환경 변수를 통해 지정할 수 있습니다. 하지만 애플리케이션 서비스의 위치를 결정하는 것은 그렇게 쉽지 않습니다. 애플리케이션 서비스에는 동적으로 위치가 할당됩니다. 또한, 자동 크기 조정 및 업그레이드로 인해 서비스 인스턴스 세트가 동적으로 변경됩니다. 따라서 API Gateway는 시스템의 다른 서비스 클라이언트와 마찬가지로 시스템의 서비스 검색 메커니즘, 즉 서버 측 검색 또는 클라이언트 측 검색을 사용해야 합니다. 이후 기사에서는 서비스 검색에 대해 더 자세히 설명하겠습니다. 지금으로서는, 시스템이 클라이언트 측 검색을 사용하는 경우 API 게이트웨이가 모든 마이크로서비스 인스턴스와 해당 위치에 대한 데이터베이스인 서비스 레지스트리를 쿼리할 수 있어야 한다는 점에 유의하는 것이 좋습니다.
API 게이트웨이를 구현할 때 해결해야 할 또 다른 문제는 부분적 실패 문제입니다. 이 문제는 모든 분산 시스템에서 하나의 서비스가 느리게 응답하거나 사용할 수 없는 다른 서비스를 호출할 때 발생합니다. API 게이트웨이는 다운스트림 서비스를 기다리면서 무기한 차단되어서는 안 됩니다. 그러나 장애를 처리하는 방법은 구체적인 시나리오와 어떤 서비스가 실패하는지에 따라 달라집니다. 예를 들어, 제품 세부 정보 시나리오에서 추천 서비스가 응답하지 않는 경우 API 게이트웨이는 사용자에게 여전히 유용하므로 나머지 제품 세부 정보를 클라이언트에 반환해야 합니다. 추천 사항은 비어 있을 수도 있고, 예를 들어 하드와이어된 상위 10개 목록으로 대체될 수도 있습니다. 그러나 제품 정보 서비스가 응답하지 않는 경우 API Gateway는 클라이언트에 오류를 반환해야 합니다.
API 게이트웨이는 캐시된 데이터가 가능한 경우 해당 데이터를 반환할 수도 있습니다. 예를 들어, 제품 가격이 거의 변경되지 않으므로 가격 책정 서비스를 사용할 수 없는 경우 API 게이트웨이는 캐시된 가격 데이터를 반환할 수 있습니다. 데이터는 API 게이트웨이 자체에서 캐싱하거나 Redis 또는 Memcached와 같은 외부 캐시에 저장할 수 있습니다. API 게이트웨이는 기본 데이터 또는 캐시된 데이터를 반환함으로써 시스템 장애가 사용자 경험에 영향을 미치지 않도록 보장합니다.
Netflix Hystrix는 원격 서비스를 호출하는 코드를 작성하는 데 매우 유용한 라이브러리입니다. Hystrix는 지정된 임계값을 초과하는 호출에 대해 시간 초과를 발생시킵니다. 이는 클라이언트가 응답하지 않는 서비스를 불필요하게 기다리지 않도록 하는 회로 차단기 패턴을 구현합니다. 서비스의 오류율이 지정된 임계값을 초과하면 Hystrix는 회로 차단기를 작동시키고 모든 요청은 지정된 기간 동안 즉시 실패합니다. Hystrix를 사용하면 요청이 실패할 때 캐시에서 읽거나 기본값을 반환하는 등의 대체 작업을 정의할 수 있습니다. JVM을 사용하고 있다면 Hystrix를 꼭 고려해 보세요. JVM이 아닌 환경에서 실행하는 경우 동등한 라이브러리를 사용해야 합니다.
대부분의 마이크로서비스 기반 애플리케이션의 경우 시스템에 대한 단일 진입점 역할을 하는 API 게이트웨이를 구현하는 것이 합리적입니다. API 게이트웨이는 요청 라우팅, 구성 및 프로토콜 변환을 담당합니다. 각 애플리케이션 클라이언트에 사용자 정의 API를 제공합니다. API 게이트웨이는 캐시된 데이터나 기본 데이터를 반환하여 백엔드 서비스의 오류를 가릴 수도 있습니다. 이 시리즈의 다음 기사에서는 서비스 간 통신에 대해 살펴보겠습니다.
편집자 – 이 7부작 시리즈 기사는 이제 완료되었습니다.
NGINX Plus를 사용하여 마이크로서비스를 구현하는 것에 대한 정보와 더불어 전체 문서 세트를 전자책으로 다운로드할 수도 있습니다. – 마이크로서비스: 설계부터 배포까지 .
추가 사용 사례에 대한 자세한 내용은 3부로 구성된 블로그 시리즈인 API 게이트웨이로 NGINX Plus 배포를 참조하세요.
게스트 블로거 크리스 리처드슨은 Amazon EC2를 위한 초기 Java PaaS(서비스형 플랫폼)인 CloudFoundry.com 의 창립자입니다. 그는 현재 기업들과 협의해 애플리케이션을 개발하고 배포하는 방식을 개선하기 위해 노력하고 있습니다. 그는 또한 http://microservices.io 에서 마이크로서비스에 관해 정기적으로 블로그를 운영하고 있습니다.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."