ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 3. MSA 구현을 위한 핵심 프레임워크를 알아보자 2
    Spring Cloud 2021. 3. 25. 23:51

    지난 장에서는 Spring Cloud의 개요와 서비스 디스커버리, 클라이언트측 부하 분산을 알아보았습니다.

    이번장에서는 API Gateway, 장애 전파방지와 복구, Config Server와 관련된 라이브러리를 알아봄으로써 Spring Cloud 전반적인 이해를 다지도록 하겠습니다.

     

    만약 아직 이전 장을 보지 못하신 분들은 "2. MSA 구현을 위한 핵심 프레임워크를 알아보자 1"을 먼저 읽어보시길 권장드립니다.

     

    API Gateway - 단일 지점

    앞장에서 작게 분리된 서비스들을 서비스 디스커버리(Eureka)를 이용하여 서로의 정보를 관리하고 클라이언트부하분산(Ribbon 이용)으로 통신한다고 하였습니다.

     

    여기서 한가지 의문점이 있습니다.

    내부에서는 디스커버리 서버를 통해 서로의 정보를 공유하고 통신하는데 문제가 없지만, 외부 클라이언트에서는 각 서비스들의 정보는 어떻게 알아야 할까요? 디스커버리 서버에 접근을 할수가 없는데 모든 서비스의 IP와 PORT를 알고 있어야 할까요?

    여기의 해답에는 API Gateway가 있습니다.

    그리고 이러한 API Gateway를 쉽게 구현할 수 있게 도와주는 도구로 Spring Cloud의 Zuul1, Zuul2, Spring Cloud gateway 등 다양한 라이브러리가 있습니다.

     

    • 여기에서 언급한 외부 클라이언트는 네트워크 외부망에서 접속하는 모든 시스템이나 이용자이거나, Legacy 시스템 혹은 또다른 네트워크 망의 사내 시스템일수도 있습니다.
    • API Gateway의 각 라이브러리의 차이점에 대해서는 추후 장에서 자세히 다뤄 보겠습니다.

     

     

    위 그림과 같이 외부에서는 내부의 서비스들을 몰라도 됩니다. 단지 공개된 규격의 URL를 이용하여 API Gateway 서버로 요청하면 API Gateway가 알아서 해당 서비스로 호출하고 응답을 받아서 외부 클라이언트에게 답해줍니다.

     

     

    상품서비스에 /display 라는 상품의 정보 반환해주는 API가 있다고 가정해봅시다.

    외부 클라이언트는 내부서비스의 유무를 몰라도 대표도메인(https://대표도메인.co.kr)공개된 URI (/api/product/display)의 호출로 통신이 가능합니다.

    여기서 의문이 생길 수도 있습니다.
    "외부 클라이언트도 결국 각각의 서비스의 ID를 알아야 되는것 아니냐?" 라는 반문을 할수도 있습니다.
    하지만, 여기서 중요한것은 외부가 봤을때 URI인 /api/product/display는 단지 상품(product)를 보여주는(display) API 라는뜻을 의미할 뿐입니다.
    외부 클라이언트 입장에서 공개된 API 규격서의 URI로 접근하는 개념이지 서비스의 ID인지 아닌지 알 필요가 없습니다.

      

     

    API Gateway - 그밖의 역할

    API Gateway는 단일지점으로서의 역할 외에도 많은 역할을 수행할 수 있습니다.

     

    그중 하나가 내/외부망의 분리로 서비스들을 안전하게 보호 하는 것입니다.

     

    위 그림과 같이 망을 분리하고 내부망으로의 통신은 API Gateway로 제한한다면 외부의 공격으로 부터 중요한 서비스들을 안전하게 보호할 수 있습니다.

     

    • API Gateway도 내부망에 두고 외부망에 Apache(웹서버)를 배치하여 Apache <-> API Gateway <-> 서비스 간 연결하는 방법이 쓰이기도 합니다.

    그 외에도 단일지점이라는 특징으로 다양한 장점을 얻을 수 있습니다.

    외부 클라이언트가 유효한 사용자인지 인증(Authentication)을 하거나 해당 사용자가 원하는 자원에 접근할 권한이 있는지 인가(Authorization)하는 등의 작업을 각 서비스가 신경 쓸 필요없이 모두 API Gateway가 처리하면 됩니다.

     

    트래픽, 요청&응답 전문 등을 로깅하기에도 API Gateway는 최적의 장소 입니다.

    그 외 모든 공통적인 요소들은 API Gateway에게 맡기면 서비스는 더욱 간결하게 본업무에만 충실할 수 있겠지요?

     

    • 주의할 점은 API Gateway가 모든 서비스의 요청을 받아주는 단일지점이기에 부하에 신경을 써야 합니다. 리소스를 많이 쓰는 작업(DB 연동, File IO 작업 등)은 피하고 가볍게 유지하는 것이 좋습니다.

     

     

    장애 전파 방지와 복구

    MSA 환경에서는 작은 서비스들이 분리된 자기 자신의 DB를 제어하며 서로 상호 소통하기에 과거 모놀리식 아키텍처보다 다양한 통신 오류 및 지연 문제가 발생할 수 있습니다.

     

    만약 하나의 서비스에 특정 기능에 문제가 생긴다면, 해당 문제점이 시스템 전체의 장애로 확산되지 않도록(Thread Isolation) 장애를 자동으로 차단하고(Circuit Breaker), 문제가 된 기능을 대체할 수 있는 기능을 응답(Fallback)할 수 있습니다.

     

    이러한 장애를 적극적으로 대응하는 여러 방안이 있으며, 이러한 구현을 쉽게 도와주는 Hystrix와 Spring Cloud의 Resilient 라이브러리가 있습니다.

     

    대표적인 장애 대응 및 복구 방안

    Hystrix의 주요 장애 대응 및 복구 방안에 대해 아래 정리하였습니다.

     

    1. Circuit Breaker

    Hystrix가 관리하는 기능들은 요청 처리에 대한 통계가 내부적으로 집계됩니다.

    통계를 분석하여 특정 기능이 일정 시간동안 일정 횟수의 요청에 대해 일정 비율로 에러(Exception)가 발생할 경우 Circuit Open 합니다.

    Circuit Open되면 이후 일정 시간동안 이후 요청(기능)을 차단함으로써 지속적으로 발생하는 에러로 인한 자원 고갈 및 반복 장애를 차단하고 복구를 위한 시간을 벌수 있습니다. 이는 서비스 간의 연계에세 연쇄적인 서비스 장애를 방지할 수 있습니다.

    이후 한 건의 요청을 허용하며 해당 요청이 성공하면 Circuit Close를 하며, 실패할 경우 다시 일정 시간 Circuit Open을 유지 합니다.

     

     

     

    2. Fallback (폴백 패턴)

    특정 기능이 실패할 경우 해당 기능을 대체하는 다른 기능을 반환 할 수 있습니다.

    예를 들어 쇼핑몰에서 특정 고객에게 맞춤형 상품을 제공하는 기능이 있다고 합시다. 만약 이 기능이 문제가 발생하였을 때, 에러화면을 그대로 고객에게 노출하는 것보다 미리 준비해둔 상품의 정보를 제공할 수 있습니다.

     

    3. Thread Isolation (벌크헤드 패턴)

    Hystrix로 감싼 기능은 Intercept되어 Hystrix가 생성한 스레드들이 대신 실행합니다.

    이때 각 기능이 사용할수 있는 자원을 격리(제한) 함으로서 1개 기능 장애가 전체 시스템에 영향을 미치는 것을 차단합니다.

    예를 들어 상품서비스의 전체 가용 자원이 100이라고 하였을때, 상품서비스의 A,B,C,D,E 기능들이 같이 자원을 공유하며 서비스가 운영됩니다.  갑자기 A기능에 부하가 심해지거나 심각한 지연이 발생하여 자원의 대다수의 점유해버립니다. 그러면 B,C,D,E는 얼마 남지 않은 자원으로 운영되다 보면 연쇄적인 장애로 이어질 수 있습니다.

    Thread Isolation을 하여 각각의 서비스에 자원을 20씩만 할당해 격리한다면 A 서비스가 20개의 자원을 모두 고갈하더라도 B,C,D,E는 영향을 받지 않게 됩니다.

     

    4. Timeout 처리

    특정시간 동안 해당 기능이 완료되지 않으면 예외를 발생합니다. 너무 긴 타임아웃을 가지는 것 또한 장애를 유발할 수 있는 요소입니다. 모든 스레드의 요청이 응답을 대기하게 되면 더이상 추가 요청을 받지 못하고 해당 요청은 대기큐에 쌓이며 밀리게 됩니다. 이에 기능별로 적절한 수치의 Timeout의 지정이 필요 할수 있습니다.

     

     

    Config Server

    서비스마다 기본적인 설정 혹은 서비스가 사용하는 정보인 환경설정을 propertis(yaml) 파일에 Key:Value 값으로 관리하고 있습니다. 만약 서비스의 수가 많아지고 각각의 서비스가 자체적으로 환경설정을 가지고 있다면 관리가 어려워집니다. 또한 빠르게 변화하는 클라우드 환경에서 매번 프로퍼티를 변경하고 배포하는 것은 쉽지 않은 일입니다.

    (컨테이너에 떠있는 프로퍼티를 직접 수정하는것은 권장하지 않습니다. 추후 변경 사항이 관리가 되지 않기 때문입니다.)

     

    이럴때 Config Server에서 중앙집중식으로 환경설정(프로퍼티)을 관리할 수 있습니다. 즉 코드와 환경설정을 분리하는 것이 Micro Services Architecture 사상에 적합니다. (Twelve factors 방법론의 드와 설정의 분리)

     

    서비스의 환경설정은 Config Server 내부에서 파일 기반으로도 관리할 수있지만, Private GIT에 관리하는 것이 여러모로 이점이 있습니다. 가장 큰 장점으로는 환경설정을 누가 왜 언제 변경하였는지 GIT의 이력을 통해 추적이 가능하여 투명하게 관리될 수 있다는 것입니다.

     

    * 보안상 GIT Server는 Private하게 구성하기 위해 외부에서 접근이 불가능한 내부망에 두어 사설IP로만 접근할 수 있게 두는 것을 권장합니다.

     

    또다른 장점으로는 프로젝트의 수정이 발생하더라도 서비스 혹은 Config Server를 재기동할 필요가 없습니다.

    스프링 부트 actuator의 /actuator/refresh API를 호출하면 변경된 프로퍼티를 가져와 바로 갱신할수 있으니까요.

    Config Server와 Git Server는 연동되어 지며, 각 서비스들은 기동시에 Config Server에 접속하여 자신의 프로퍼티 정보를 가져갑니다. 개발자는 언제든지 필요에 따라 프로퍼티 수정을 할 수 있습니다.

     

    정리

    이번 장에서 API Gateway, 장애 전파방지와 복구, Config Server와 관련된 라이브러리를 알아봄으로써 MSA 구현을 위한 Spring Cloud 핵심 기술들을 이해하였습니다.

    다음장부터는 지금까지 익혀온 이론을 기반으로 실제 MSA 프로젝트를 구축해 보도록 하겠습니다.

    댓글

Designed by Tistory.