Summary

대부분의 microservice기반 어플리케이션에 대해서 시스템으로 접근하는 단일 접점 포인트로 동작하는 API Gateway를 구현하는 것이 좋다. API Gateway는 request routing(요청 전송), composition(구성), protocol translation(프로토콜 변환)에 대해 책임을 진다. API Gateway는 어플리케이션의 각 client에 Custom API를 제공한다. API Gateway는 또한 캐시되어 있는 데이터나 기본 데이터를 리턴하여 backend service의 실패를 감출 수 있다. 시리즈의 다음 article에서는 서비스들 사이의 통신에 대해서 살펴볼 것이다.
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/757

Implementing an API Gateway

이제, API Gateway를 사용하는 것에 대한 동기부여와 trade-off(서로 대립되는 요소 사이의 균형점)에 대해서 살펴봤는데, 이제 고려해야할 다양한 디자인 이슈에 대해서 살펴보자.

Performance and Scalability
(성능과 확장성)

단지 몇개의 회사만 Netflix의 규모로 운영되고 있고, 하루에 수십억건의 요청을 처리할 필요가 있다. 그러나, 일반적으로 API Gateway의 성능과 확장성은 대부분의 어플리케이션에서 매우 중요하다. 그러므로 플랫폼에서 Asynchronous, Non-blocking I/O를 지원하는 API Gateway 만드는 것이 필요하다. 확장 가능한 API Gateway를 구현하기 위해 사용하는 기술들은 다양하다. JVM상에서 Netty, Vertx, Spring Reactor, JBoss Undertow와 같은 NIO(Non-Blocking I/O) 기반 framework를 사용할 수도 있다. 일반적으로 Chrome의 Javascript engine인  Node.js도 non-JVM 기반의 한가지 선택이 될 수 있다. 또다른 선택은 NGINX PLUS를 사용하는 것이다. NGINX PLUS는 성숙하고 확장 가능하며 고성능의 웹 서버와 쉽게 배포할 수 있고, 설정 가능하고, 프로그램될 수 있는 reverse proxy를 제공한다. NGINX PLUS는 authentication(인증), access control(접근제어), load balancing requests(요청 부하 분산), caching responses(응답 캐싱), 어플리케이션을 인식하는 health check와 모니터링을 관리할 수 있다.

Using a Reactive Programming Model
(반응 프로그래밍 모델 사용:이벤트를 비동기 데이터 흐름으로 보는 프로그래밍 방법)

API Gateway는 어떤 요청들에 대해서는 간단히 적합한 backend service로 전달한다. 다른 요청들에 대해서는 여러 개의 backend service를 호출하고, 그 결과를 취합한다. 상품 상세 정보 요청과 같은 어떤 요청들은 서로 독립적인 backend service에 요청하기도 한다. 응답 시간을 최소화하기 위하여, API Gateway는 동시에 독립적으로 요청을 처리해야 한다. 그러나, 때때로 요청 사이에는 의존 관계가 있다. API Gateway는 요청을 backend service로 전달하기 전에, 처음에 authentication service(인증 서비스)를 호출하여 요청에 대해 인증할 필요가 있다. 이와 유사하게, 고객의 wish list에서 상품에 대한 정보를 가져오려고 할 때, API Gateway는 먼저 정보를 담고 있는 고객의 프로파일을 조회하고, 각 상품에 대한 정보를 조회해야만 한다. API composition(구성)의 또다른 흥미로운 예제는 Netflix Video Grid이다.

전통적인 asynchronous callback approach로 API composition code를 작성하면, 여러분은 빠르게 callback hell에 빠지게 된다. Code는 꼬이고, 이해하기 어렵고, 오류가 발생하기 쉽다. 더 좋은 방법은 reactive approach를 사용하여 서술 형태로 API Gateway Code를 작성하는 것이다. Scala의 Future, Java 8의 CompletableFuture, Javascript의 Promise가 reactive abstraction의 예이다. 물론, .ㅜNET Platform을 위해서 Microsoft에서 개발한 Reactive Extension(Rx or ReactiveX라고도 불린다.)도 있다. Netflix는 그들의 API Gateway에서 특별하게 사용하기 위해 JVM에 대한 RxJava를 만들었다. 물론 브라우저와 Node.js에서 모두 동작하는 Javascript를 위한 RxJS도 있다. Reactive approach를 사용하면 API Gateway code를 굉장히 효율적으로 작성할 수 있을 것이다.

Service Invocation
(서비스 호출)

Microservice기반 어플리케이션은 분산 시스템이기 때문에 inter-process communication mechanism(프로세스간 통신 매커니즘)을 사용해야만 한다. Inter-process communication에는 2가지 형태가 있다. 한가지는 비동기 메시지 기반 메커니즘을 사용하는 것이다. JMS나 AMQP와 같은 message broker를 사용하여 구현한다. 나머지는 ZEROMQ처럼, broker 없이 서비스들이 직접 통신하는 메커니즘이다. 또다른 inter-process communication 형태는 HTTP나 Thrift와 같은 비동기 메커니즘이다. 시스템은 동기, 비동기 모두 사용할 수도 있고, 각각의 형태의 여러 구현체들을 사용할 수도 있다. 따라서, API Gateway는 다양한 통신 매커니즘을 지원해야 한다.

Service Discovery
(서비스 발견)

API Gateway는 통신할 각 microservce들의 위치(IP 주소와 port)를 알고 있어야 한다. 고전적인 어플리케이션에서는 위치를 고정시켰으나, cloud기반 microservice 어플리케이션인 현대에는 심각한 문제이다. Message broker와 같은 기초적인 서비스는 OS 환경 변수를 통해 특정지을 수 있는 고정 주소를 가지고 있을 것이다. 그러나, application service의 위치를 결정하는 것은 그렇게 쉽지 않다. Application service는 동적으로 지정된 주소를 가지고 있다. 또한, service의 여러 instance들은 autoscaling과 upgrade때문에 동적으로 변한다. 따라서, 시스템에서 다른 서비스의 클라이언트와 같은 API Gateway는 시스템의 서비스를 발견하는 메커니즘을 사용해야 한다. 그것이 Server-side Discovery이건 Client-side Discovery이건 간에. 나중에 service discovery에 대해서는 더 자세히 다룰 것이다. 우선은 시스템이 Client-Side Discovery를 사용한다면 API Gateway가 모든 microservice instance들과 그 위치에 대한 데이터베이스인 Service Registry에 질의할 수 있어야 하는 것에 대해서 기록할만한 가치가 있다.

Handling Partial Failures
(부분적인 실패 처리)

API Gateway를 구현할 때 고민해야할 또다른 이슈는 부분적인 실패에 대한 문제이다. 이 이슈는 하나의 서비스가 또다른 서비스를 호출할 때, 느리게 응답하거나 사용불가능한 경우, 언제든지 모든 분산 시스템에서 발생한다. API Gateway는 downstream service(API Gateway에서 요청을 전송한 서비스)에 대해서 무한대로 기다리며 차단하지 않아야 한다. 그러나, 특정 시나리오에서 발생하는 실패와 서비스가 실패하는 경우는 어떻게 다루어야 하는가? 예를 들면 상품 상세 정보 시나리오에서 추천 서비스가 응답하지 않는다면, API Gateway는 아직 사용자가 사용중이기 때문에 client에 나머지 상품 상세 정보를 보내 주어야 한다. 추천 내용은 비어 있거나, 예를 들어 고정된 top 10 리스트 같은 내용으로 교체될 것이다. 그러나 만약 상품 정보 서비스가 응답을 하지 못하는 상황이라면 API Gateway는 client에 에러를 리턴해야 한다.

API Gateway는 캐시를 사용할 수 있도록 되어 있을 경우, 캐시된 데이터를 리턴할 수도 있다. 예를 들어 상품 가격이 수시로 변경될 경우 API Gateway는 상품 가격 서비스를 이용할 수 없을 경우, 캐시된 상품 가격 데이터를 리턴할 수 있다. 데이터는 API Gateway 자체에 캐시되거나 Redis, Memcached와 같은 외부 캐시에 저장될 수 있다. 기본 데이터나 캐시 데이터를 리턴하여 API Gateway는 시스템에서 발생한 실패가 사용자 경험에 영향을 미치지 않도록 한다.

Netflix Hystrix는 remote service를 호출하는 code를 작성하는데 믿을 수 없을 정도로 유용한 라이브러리이다. Hystrix는 특정 한계점을 넘어서는 호출을 중지시킨다. Circuit breaker pattern으로 구현되었는데, 응답하지 않는 서비스에 대해서 client가 불필요하게 기다리는 것을 멈추게 한다. 만약 서비스의 error rate가 특정 한계점을 넘어간다면, Hystrix는 circuit breaker를 작동시키고, 모든 요청들은 즉시 특정 기간동안 실패할 것이다. Hystrix는 캐시를 읽거나 기본값을 리턴하는 것과 같은 요청이 실패할 때, callback action을 정의할 수 있다. 만약 JVM을 사용한다면 Hystrix를 사용하는 것을 분명히 고려해 보라. 만약 non-JVM 환경에서 구동시키고 있다면, 동등한 라이브러리를 사용해야 한다.
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/756

Benefits and Drawbacks of an API Gateway
(API Gateway의 유익한 점과 문제점)

여러분이 기대한 대로, API Gateway를 사용하는 것은 유익한 점과 문제점이 있다. API Gateway를 사용함으로써 얻는 주요 장점은 어플리케이션의 내부 구조를 보호할 수 있다는 것이다. 클라이언트에서 특정 서비스를 호출해야 하는 것보다 더 간단하게 gateway와 통신할 수 있다. API Gateway는 클라이언트 종류에 따라 맞는 특화된 API를 제공한다. 이것은 클라이언트와 어플리케이션간의 round trip(왕복)을 줄여 준다. 그리고 클라이언트의 코드를 단순하게 한다.

API Gateway는 또한 문제점도 있다. API Gateway는 개발하고, 배포하고, 관리해야 하는 또다른 고가용성의 컴포넌트이다. 또한 API Gateway는 개발 병목지점이 되는 리스크도 안고 있다. 개발자들은 각각의 microservice의 endpoint를 노출시키기 위하여 API Gateway를 업데이트 해야 한다. 가능한한 가엽게 API Gateway를 업데이트할 수 있는 프로세스가 중요하다. 반면에 개발자들은 gateway를 업데이트하기 위해 줄서서 기다리기를 강요당할 것이다. 그러나, 이러한 문제점에도 불구하고 대다수 실제 상용 환경의 어플리케이션에서 API Gateway를 사용하는 것은 타당하다.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/755

Using an API Gateway

일반적으로 API Gateway로 알려진 것을 사용하는 것이 훨씬 더 좋은 방법이다. API Gateway는 시스템으로 접속하는 단일 진입점 서버이다. Object-Oriented 디자인에서 Facade 패턴과 유사하다. API Gateway는 내부 시스템 아키텍처를 보호하고, 개별 클라이언트에 맞춰진 API를 제공한다. API Gateway는 Authentication(인증), monitoring, load balancing, caching, request shaping(요청 제어) and management(관리), static response handling(정적 응답 처리)를 책임지고 수행한다.

다음 그림은 아키텍처상에서 API Gateway가 어떻게 표현되는지를 보여준다.

사용자 삽입 이미지

API Gateway는 request routing, composition, protocol translation에 대해 완결적으로 수행한다. 클라이언트에서 하는 모든 요청들은 API Gateway를 통과하게 된다. 그리고 그 요청들은 적합한 micro service들에게 라우팅된다. API Gateway는 종종 하나의 요청에 대해 여러 개의 microservice들을 호출하고, 그 결과를 취합하여 응답을 제공할 것이다. API Gateway는 HTTP나 WebSocket과 같은 Web Protocol을 내부에서 사용하는 웹친화적이지 않은 프로토콜로 변환할 수 있다.

API Gateway는 개별 클라이언트에 Custom API를 제공할 수도 있다. 일반적으로 Mobile client에 대해서는 거친 API를 노출한다. 예를 들어, 상품 상세 정보 제공 시나리오를 생각해 보라. API Gateway는 모바일 클라이언트에서 한번의 요청으로 모든 상품의 상세 정보를 얻을 수 있는 하나의 endpoint(/productdetails?productid=xxx)를 제공할 수 있다. API Gateway는 그 요청을 처리하기 위해 다양한 서비스들(product info, recommendations, reviews, etc.)을 호출하고 그 결과를 조합한다.

API Gateway의 가장 좋은 예제는 Netflix API Gateway이다. Netflix streaming service는 televisions, set-top boxes, smartphones, gaming systems, tablets등등의 수백개의 서로 다른 종류의 다비이스에서 사용할 수 있다. 초기에 Netflix는 streaming service를 위해 임의의 크기(one-size-fits-all) API를 제공하려고 했다. 그러나 다양한 범위의 디바이스와 디바이스별 특정 요구사항 때문에 잘 동작하지 않는다는 것을 발견했다. 오늘날, Netflix는 device-specific adapter code를 실행하여 각각의 디바이스에 맞춰진 API르르 제공하는 API Gateway를 사용한다. Adapter는 일반적으로 평균 6~7개의 backend service를 호출하여 각 요청을 처리한다. Netflix API Gateway는 하루에 수십억건의 요청을 처리한다.

받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/754

Summary

복잡한 어플리케이션을 만드는 것은 본질적으로 어렵다. Monolithic Architecture는 단지 간단하고 가벼운 어플리케이션에 맞다. 만약 Monolithic Architecture를 복잡한 어플리케이션에 사용한다면, 여러분은 결국 고통의 세계로 끝나게 될 것이다. Microservice Architecture Pattern은 여러 단점들에도 불구하고 복잡하고, 발전하는 어플리케이션과 도전을 성취하는데 있어 더 좋은 선택이다.

이후 블로그 포스트에서는, Microservice Architecture Pattern의 다양한 측면에서 상세하게 들어가 볼 것이다. 그리고 service discovery, service deployment options, monolithic application을 service로 리팩토링하는 전략과 같은 주제들에 대해서 논의할 것이다.

계속해서 주목해 보라....(Stay tuned...)
받은 트랙백이 없고, 댓글이 없습니다.

댓글+트랙백 RSS :: http://www.yongbi.net/rss/response/751