03_스프링 클라우드 개요
1장 마이크로서비스의 개요에서 클라우드-네이티브 개발 스타일과 마이크로서비스의 개념과 관련된 모범사례를 쉽게 적용하도록 도와주는 스프링 클라우드를 살펴봤다. 가장 많이 사용되는 모범사례는 12-팩터 앱(The Twelve-Factor App)인데, 이것은 확장이 가능하고 쉽게 클라우드 플랫폼에 배포할 수 있으면 지속 배포 프로세스에 따라 배포되는 SaaS(Software as a Service)를 개발하는 방법론이다. (참고 URL https://12factor.net/)
스프링 부트와 스프링 클라우드는 12-팩터룰에 부합하는 애플리케이션을 만드는 기능과 요소를 제공한다.
이런 기능에는 다음과 같은 것이 있다.
- 분산/버전 컨피규레이션
- 서비스 등록 및 디스커버리
- 라우팅
- 서비스 간의 호출
- 부하 분산
- 서킷 브레이커
- 분산 메시징
1. 기본부터 시작하기
- 표준 스프링 부트 애플리케이션과 달리 스프링 클라우드는 원격 서버에서 컨피규레이션을 가져옴
- 부트스트랩 컨텍스트
- 애플리케이션 내에 필요한 최소 설정(ex 애플리케이션 이름, 컨피규레이션 서버 주소 등)으로 스프링 클라우드 프로젝트가 외부 소스에서 컨피규레이션을 읽어올 수 있도록 함
- 메인 애플리케이션 컨텍스트의 부모(parent)로 스프링 부트의 application.yml 대신 bootstrap.yml을 사용함
- 부트스트랩 컨텍스트를 비활성화하려면 설정 파일에서 spring.cloud.bootstrap.enabled 속성을 false로 설정함
- 부트스트랩 컨피규레이션 파일의 이름은 spring.cloud.bootstrap.name 속성으로 변경 가능하고, spring.cloud.bootstrap.location 설정으로 설정 파일의 위치 변경 가능
- 프로파일 메커니즘 가능. bootstrap-deployment.yml 파일을 생성하면 development 프로파일이 활성화될 때 이 파일리 로딩됨. 이러한 기능은 프로젝트 클래스 경로에 부모 의존성이 등록될 때 자동으로 포함하는 스프링 클라우드 컨텍스트 라이브러리에서 사용할 수 있음. 이런 기능 중 하나로 스프링 부트 액추에이터에 포함된 관리 종단점이 있음
- 스프링 클라우드 커먼즈(Spring Cloud Commons)
- 스프링 클라우드 프로젝트에 부모 의존성으로 포함된 라이브러리
- 서비스 디스커버리, 부하 분산, 서킷 브레이커 등의 메커니즘을 위한 공통의 추상 레이어 제공
- @EnableDiscoveryClient 또는 @LoadBalanced 등의 자주 쓰이는 애너테이션 포함
- 넷플릭스(Netflix) OSS(Open Source Software)
- 모놀리식 애플리케이션 기반의 전통적인 개발 모델에서 클라우드-네이티브 마이크로서비스 기반 개발 방식으로 전환한 선구자
- 스프링 크라우드는 넷플릭스의 유명한 오픈 소스 기능인 유레카(Eureka), 히스트릭스(Hystrix), 리본(Ribbon), 주울(Zuul) 등과 통합됨
- 유레카를 사용한 서비스 디스커버리
- 유레카는 서비스 디스커버리로 이 패키지는 클라이언트와 서버로 구분됨
- 유레카 클라이언트
- 유레카 클라이언트를 프로젝트에 포함하려면 spring-cloud-starter-eureka 스타터를 사용함
- 클라이언트는 항상 애플리케이션의 일부로 원격의 디스커버리 서버에 연결하는 일을 담당하고 연결되면 서비스 이름과 네트워크 위치를 담은 등록 메시지를 보냄
- 현재 마이크로서비스가 다른 마이크로서비스의 종단점을 호출해야 할 경우 클라이언트는 서버로부터 등록된 서비스 목록을 담은 최신의 컨피규레이션을 가져옴
- 유레카 서버
- 유레카 서버를 프로젝트에 포함하려면 spring-cloud-starter-eureka-server 스타터를 사용함
- 서버는 독립적인 스프링 부트 애플리케이션으로 설정되고 실행되는데 각 서버의 상태를 다른 서버에 복제해 가용성(시스템 품질 속성 중 시스템이 장애없이 정상적으로 운영되는 능력)이 높음
- 주울을 사용한 라우팅
- 주울(Zuul)은 JVM 기반의 라우터이며 서버 측 부하 분산과(이나) 일부 필터링을 수행함
- 폭넓은 곳에 적용가능. 넷플릭스에서는 주울을 인증이나 부하 평균 분배, 정적 응답 처리. 부하 테스트에 사용함
- 주울은 설정 가능하고 독립적인 스프링 부트 애플리케이션으로 실행된다는 점에서 유레카 서버와 같음
- 주울을 프로젝트에 포함하려면 spring-cloud-starter-zuul 스타터를 사용함
- 마이크로서비스 아키텍처에서 주울은 전체 시스템의 진입점을 제공하는 API 게이트웨이로서 중요한 역할을 함
- 이를 위해 주울은 각 서비스의 네트워크 위치 정보를 알아야 하므로 유레카 서버와 통신하기 위해 디스커버리 클라이언트를 클래스 경로에 포함함
- 리본을 사용한 부하 분산
- 리본(Ribbon)은 클라이언트 측 부하 분산기로 TCP, UDP, HTTP 등 가장 유명한 프로토콜을 지원함
- 동기 방식의 REST 호출뿐만 아니라 비동기 또는 리액티브 모델도 지원
- 부하 분산 외에도 서비스 디스커버리, 캐싱, 일괄 처리, 장애 내성과 통합할 수 있음
- 리본은 기본 HTTP와 TCP 클라이언트를 한 단계 더 추상화함
- 리본을 프로젝트에 포함하려면 spring-cloud-starter-ribbon 스타터를 사용함
- 리본은 라운드 로빈, 가용성 필터링, 응답 시간에 가중치를 두어 부하 분산 하는 등의 규칙을 즉시 제공하고 사용자 정의 규칙을 쉽제 확장할 수 있음
- 리본은 이름 기반 부하 분산을 하는 네임드 클라이언트(named client) 개념에 기반함
- 자바 HTTP 클라이언트 작성하기
- 페인(Feign)은 선언적인 REST 클라이언트로, 웹 서비스 클라이언트를 쉽게 작성하도록 도와줌
- 페인을 사용하면 개발자가 애노테이션을 선언하기만 하면 애플리케이션이 실행될 때 실제 구현이 실행됨
- 페인을 프로젝트에 추가하려면 spring-cloud-starter-feign 스타터를 사용함
- spring-cloud-starter-feign은 리본 클라이언트와 통합돼 디스커버리 서비스와의 통신, 부사 분산 같은 리본의 기능을 기본으로 제공함
- 히스트릭스를 사용해 대기 시간 및 장애 내성 다루기
- 스프링 클라우드는 넷플릭스에서 서킷 브레이커 패턴을 구현한 히스트릭스 패키지에 기반한 라이브러리가 있음
- 히스트릭스는 기본적으로 리본과 페인 클라이언트를 통합할 수 있음
- 폴백(fallback)은 서킷 브레이커 개념과 매우 밀접한 관련이 있음
- 스프링 클라우드 라이브러리를 사용하면 서킷 브레이커 시간 만료(timeout)가 발생했을 때 실행돼야 하는 폴백 로직을 쉽게 설정할 수 있음
- 히스트릭스를 프로젝트에 추가하려면 spring-cloud-starter-hystrix 스타터를 사용함
- 아카이우스를 사용한 컨피규레이션 관리
- 스프링 클라우드는 아파치 커먼즈 컨피규레이션 프로젝트(Apache Commons Configuration project)의 확장인 아카이우스를 참조함
- 아카이우스는 변경 전의 원본을 가져오거나 변경사항을 클라이언트에 전달하는 방법으로 컨피규레이션을 갱신함
2. 디스커버리와 분산 컨피규레이션
- 서비스 디스커버리와 분산 컨피규레이션 관리는 마이크로서비스 아키텍처에서 중요한 부분임. 이 서로 다른 메커니즘은 기술적으로 매우 비슷하게 구현됨. 결국 유연한 키-값 저장소에 특정 키와 값을 저장하는 것. 이런 기능을 제공하는 상용 솔루션 중 스프링 클라우드가 가장 인기 있음
- 스프링 클라우드만의 한 가지 특징은 분산 설정 기능을 직접 구현함. 이 기능은 스프링 클라우드 컨피그 프로젝트에 있음. 반대로 스프링 클라우드 서비스 등록 및 디스커버리를 위해서는 직접 구현한 것이 없음
- 서버 측과 클라이언트 측 지원으로 나뉨
- 서버
- 단 하나의 중앙의 장소로, 애플리케이션을 위한 모든 외부 속성이 모든 환경에 대해 서버에서 관리됨
- 컨피규레이션은 여러 버전과 프로파일로 동시에 유지됨
- 저장소 백엔드로 깃을 사용함
- 설정 파일은 파일 시스템 또는 서버 클래스 경로에도 있을 수 있음
- 볼트(Vault)를 백엔드로 사용할 수 있음
- 볼트는 토큰이나 패스워드, 자격 증명을 관리할 수 있는 해시코프(HashiCorp)에서 만든 오픈 소수 도구. 많은 조직에서 자격 정보 등을 안전한 장소에 저장하는 등의 보안 이슈에 관심을 기울이고 있는데, 볼트가 그 해결책이 될 수 있음
- 볼트를 이용하면 컨피규레이션 서버의 접근 레벨을 안전하게 관리할 수 있음
- 속성 저장소 백엔드가 무엇이든 스프링 클라우드 컨피그 서버의 HTTP와 리소스 기반 API를 통해 속성에 쉽게 접근할 수 있음
- 이 API는 기본 인증으로 보호됨. 개인 키/ 공개 키 인증을 사용한 SSL 연결도 설정할 수 있음
- 컨피그 서버
- REST API에 속성을 노출하는 독립된 스프링 부트 애플리케이션으로 실행됨
- 프로젝트에 spring-cloud-config-server 의존성을 추가해 활성화함
- 클라이언트
- 컨피규레이션 서버에 접솔할 수 있는 클라이언트 라이브러리 지원
- 컨피규레이션 서버를 속성 저장소로 사용하는 모든 마이크로 서비스 클라이언트는 클라이언트가 시작되고 스프링 빈이 생성되기 전에 컨피규레이션 서버에 접속함
- 클라이언트 측에서 스프링 클라우드 컨피그 클라이언트를 활성화하려면 프로젝트에 spring-cloud-config-starter 의존성을 포함함
- 또 다른 대안 - 컨설
- 컨설 서버에 연결하기 위해서는 애플리케이션에 에이전트가 필요함. 이는 별도로 분리된 프로세스로 실행해야 하는데, 기본으로 http://localhost:8500이라는 주소로 제공됨
- 컨설에는 서비스 등록이나 서비스 목록 수집, 속성의 컨피규레이션을 직접 수행할 수 있는 REST API가 있음
- 프로젝트에 spring-cloud-starter-consul-discovery 의존성을 사용
- 클라이언트 애플리케이션을 시작한 후 컨설 서버에 등록되면 클라이언트가 다른 서비스 목록을 가져오기 위해 컨설에 물어봄
- 컨설은 넷플릭스 리본과 동적 라우터, 넷플릭스 주울의 필터를 지원함
- 아파치 주키퍼
- 아파치 주키퍼(Zookeeper)는 컨피규레이션과 이름을 유지하는 중앙 서비스로의 분산 동기화, 그룹 서비스를 가능하게 함
- 컨설에 적용되는 스프링 클라우드와 관련된 모든 것이 주키퍼에도 적용됨
- 예를 들어, 간단한 공통 애노테이션을 통한 통합제공, 설정 파일의 속성을 통한 컨피규레이션, 그리고 리본 또는 주울과 상호작용하기 위한 자동-컨피규레이션 등이 있음
- 클라이언트 측에 주키퍼를 사용한 서비스 디스커버리를 사용하려면 spring-cloud-starter-zookeeper-discovery와 아파치 큐레이터(Curator)를 의존성에 포함함
- 큐레이터는 통합을 쉽고 믿을 만하게 해주는 API 프레임워크와 유틸리티를 제공함
- 분산 컨피규레이션 클라이언트를 활성화하기 위해서는 spring-cloud-starter-zookeeper-config 의존성을 프로젝트에 추가함
- 기타 프로젝트
- 인큐베이션 단계에 있는 다른 두 개의 프로젝트
- 스프링 클라우드 쿠버네티스(Kubernetes)
- 구글에서 설계된 시스템
- 배포, 확장, 애플리케이션 컨테이너의 관리를 자동화하는 시스템
- 프로젝트에 spring-cloud-starter-kubernetes 스타터를 포함하여 사용
- 스프링 클라우드 에티시디(Etcd)
- 주요한 기능은 분산 컨피규레이션, 서비스 등록, 디스커버리
- 에티시디는 쿠버네티스만큼 강력하지 않음
- But, 클러스터 환경에서 분산 키-값 저장소를 신뢰성 있게 제공함
- 에티시디는 쿠버네티스에서 서비스 디스커버리, 클러스터 상태, 컨피규레이션 관리에 쓰이는 백엔드
3. 슬루스를 사용한 분산 추적
- 스프링 클라우드 슬루스(Sleuth) 라이브러리가 스프링 클라우드의 필수 기능 중 하나인 분산 추적을 구현함
- 슬루스의 가장 중요한 목표는 하나의 요청을 여러 마이크로서비스로 처리할 때 이어지는 요청을 연관 짓는 것
- 대부분의 경우 HTTP 헤더에 기반한 메커니즘으로 추적을 구현함
- Slf4j와 MDC로 개발됨
- 추적을 위한 헤더 정보를 추가할 수 있음
- 지연 분석을 위한 기간정보를 기록할 수 있음. 이 통계 정보는 시간 정보를 질의하고 시각화하는 집킨(Zipkin) 도구에 제공할 수 있음
- 집킨이란?
- 집킨은 마이크로서비스 아키텍처 내부의 지연 문제를 분석하기 위해 설계된 분석 추적 시스템
- 입력 데이터를 수집하기 위한 HTTP 종단점을 노출함
- 집킨으로 추적 데이터를 생성해 보내려면 spring-cloud-starter-zipkin 의존성을 프로젝트에 추가함
- 데이터 크기가 클 때 분석 솔루션
- 스프링 클라우드 슬루스의 샘플링 정책은 입력 트래픽 양이 너무 클 때 일부 데이터만 수집할 수 있도록 함
- 기본 HTTP 종단점 대신 메시지 브로커에 통계 정보를 보내는 것
- 프로젝트에 spring-cloud-sleuth-stream 의존성을 추가하면 기능이 활성화되고, 애플리케이션은 아파치 카프카나 래빗엠큐로 메시지를 보내는 프로듀서(producer)가 됨
4. 메시징과 통합
- 스프링 클라우드는 동기/비동기 HTTP 통신과 메시지 브로커를 지원함
- 스프링 클라우드 버스를 통해 컨피규레이션 속성 변경이나 다른 관리 명령 등의 상태 변경을 브로드캐스트 이벤트(broadcast event)로 애플리케이션에 알릴 수 있음
- 래빗엠큐나 아파치카프카를 사용하는 AMQP 스타터를 사용할 수 있음. 일반적으로 spring-cloud-starter-bus-amqp 또는 spring-cloud-starter-bus-kafka 의존성만 추가하면 됨. 기타 필요한 것은 자동 컨피규레이션을 통해 수행됨
- 스프링 클라우드 버스는 다소 작은 프로젝트로, 컨피규레이션 변경 이벤트 전달 등 공통 오퍼레이션을 위한 분산 메시징 기능 사용할 수 있음
- 스프링 클라우드 스트림
- 메시지 중심 마이크로서비스로 구성된 시스템을 개발하기 위한 올바른 프레임워크
- 두 개의 바인더 존재
- 래빗엠큐를 사용하는 AMQP
- 아파치 카프카
- 스프링 인테그레이션에 기반함
- 종단점, 채널, 애그리게이터(aggregator), 트랜스포머(transformer)와 같은 대부분의 엔터프라이즈 통합 패턴을 지원하는 프로그래밍 모델 제공
- 전체 마이크로서비스 시스템 내의 애플리케이션은 스프링 클라우드 스트림 입력 및 출력 채널을 통해 통신함
- 주된 통신 모델은 게시/구독으로 메시지가 공유된 토픽을 통해 전파됨
- 그루핑(grouping) 메커니즘을 만든 이유?
- 대부분 메시지는 하나의 인스턴스에서 처리돼야 하는데, 게시/구독 모델에서는 지원하지 않기 때문
- 메시지는 목적지 그룹의 오직 한 멤버만 수신함
- 스타터 바인딩 타입에 따라 spring-cloud-starter-stream-kafka 또는 spring-cloud-starter-stream-rabbit 중 하나를 프로젝트에 추가함
- 관련있는 두 개 프로젝트
- 스프링 클라우드 스트림 앱 스타터(Spring Cloud Stream App Starter) 프로젝트
- 독립적으로 실행되는 스프링 클라우드 애플리케이션을 정의하거나 두 번째 프로젝트인 스프링 클라우드 데이터 플로우를 사용하는 스프링 클라우드 스트림 애플리케이션을 정의함
- 스프링 클라우드 데이터 플로우
- 데이터 통합과 실시간 데이터 처리 파이프라인을 만들기 위한 유용한 솔루션을 제공해 개발과 배포를 간단하게 만듦
- 마이크로서비스 기반 데이터 파이프라인의 오케스트레이션은 간단한 DSL, 드래그 앤드 드롭 UI 대시보드, REST API를 통해 수행할 수 있음
- 클라우드 플랫폼 지원
- 피보탈 클라우드 파운드리(PCF, Pivotal Cloud Foundry)
- 최신 애플리케이션을 배포하고 관리하는 클라우드 네이티브 플랫폼
- PCF는 스프링 부트의 실행 가능한 JAR 파일과 컨피그 서버, 서비스 레지스트리, 서킷 브레이커 등 모든 스프링 클라우드 마이크로서비스 패턴을 완전히 지원함
- 애플리케이션 프로젝트에 필요한 스타터
- spring-cloud-services-starter-circuit-breaker
- spring-cloud-services-starter-config-client
- spring-cloud-services-starter-service-registry
- 스프링 클라우드도 AWS를 지원함
- Spring Cloud AWS Core
- spring-cloud-start-aws 스타터로 활성화
- EC2인스턴스로 직접 접근을 활성화하는 핵심 구성 요소 제공
- Spring Cloud AWS Context
- S3 저장소, 이메일 서비스, 캐싱 서비스로의 접근 제공
- Spring Cloud AWS JDBC
- spring-cloud-starter-aws-jdbc 스타터로 활성화
- 스프링에서 지원하는 데이터 접근 기술을 사용할 수 있는 데이터 소스 조회 및 컨피규레이션 제공
- Spring Cloud AWS Messaging
- spring-cloudstarter-aws-messaging 스타터로 활성화
- 애플리케이션이 SQS(점재점 메시징) 또는 SNS(게시/구독 메시징)로 메시지를 보내고 받을 수 있게 함
- 스프링 클라우드 펑션(Function) 프로젝트는 서버리스(serverless) 아키텍처를 지원
- 서버리스는 FaaS(Function-as-a-Service)로 알려짐
- FaaS란?
- 서드파티가 제공하고 관리하는 컨테이너 서비스에 개발자가 매우 작은 모듈을 개발해서 배포함
- 스프링 클라우드 펑션은 가장 유명한 FaaS 제공자인 AWS 람다(Lambda)와 아파치 오픈위스트(OpenWhisk)를 위한 어댑터 지원
- 스프링 클라우드 커넥터 프로젝트
- 클라우드 플랫폼에 배포된 JVM 기반 애플리케이션을 위한 추상화 제공
- 히로쿠(Heroku)와 클라우드 파운드리 지원하는데, 이는 애플리케이션이 스프링 클라우드 히로쿠 커넥터와 스프링 클라우드 파운드리 커넥터 모듈을 사용해 SMTP, 래빗엠큐, 레디스(Redis) 또는 전통적인 데이터베이스에 접속할 수 있는 클라우드 플랫폼
5. 다른 유용한 라이브러리
- 보안
- 스프링 클라우드 시큐리티
- 싱글 사인온(single sign-on)과 토큰 리플레이(token reply)와 같은 일반적인 패턴을 구현하는 시스템을 쉽게 개발하게 도와줌
- spring-cloud-starter-security 스타터로 활성화
- 테스트 자동화
- 마이크로서비스 아키텍처에서 컨트랙트 테스트(Contract Test)의 중요성이 점점 커짐
- "통합 컨트랙트 테스트(integration contract test)는 소비자가 기대하는 계약을 서비스가 만족하는지 검증하는 테스트다" by 마틴 파울러(Martin Fowler)
- 스프링 클라우드 컨트랙트 프로젝트
- 단위 테스트에 이러한 접근을 하는 매우 흥미로운 프로젝트
- 트래픽을 기록하는 데 와이어목(WireMock)을 사용하고 스텁(stub)을 생성하는 데 메이븐 플러그인을 사용
- 스프링 클라우드 태스트
- 개발자가 스프링 클라우드를 사용해 한 번만 실행하고 종료하는 마이크로서비스를 개발하도록 도움
- 로컬 컴퓨터나 클라우드 환경에서 실행함
- spring-cloud-starter-task 스타터로 활성화
- 클러스터 기능
- 주키퍼, 레디스, 해즐캐스트(Hazelcast), 컨설에 대한 추상화 및 구현을 사용해 리더 선출과 공통 상태유지 패턴을 위한 솔루션 제공
6. 프로젝트 개요
- 스프링 클라우드는 수많은 서로 다른 도구의 솔루션의 통합을 제공하는 다수의 하위 프로젝트로 구성됨
- 중요한 프로젝트를 범주에 따라 구분해 아래 다이어그램으로 나타냄
7. 릴리즈 트레인(release trains)
- 스프링 클라우드 내에는 수많은 프로젝트가 있고 프로젝트 간의 관계도가 많음
- 프로젝트는 모두 다른 릴리즈 주기와 버전 번호를 갖는 독립적인 프로젝트
- 이런 상황에서 애플리케이션의 의존성 관리는 문제가 될 수 있고 모든 프로젝트 버전 간의 관계를 알아야 하는 문제가 있음
- 이런 문제를 쉽게 처리하기 위해 스타터 메커니즘과 릴리즈 트레인을 도입함
- 릴리즈 트레인
- 하위 프로젝트의 혼란을 피하기 위해 릴리즈를 버전이 아닌 이름으로 구분
- 런던 지하철 역의 이름에 따라 알파벳 순서로 사용
- 스타터 메커니즘
- 의존성 관리의 전체 메커니즘은 BOM(Bill of materials)에 기반함
- BOM은 아티팩트 버전을 독립적으로 관리하는 표준 메이븐 개념
- M[X]: M은 마일스톤(milestone), X는 버전 번호
- SR[X]: 서비스 릴리즈(service release)로서 중요한 버그를 수정한 버전
8. 요약
스프링 클라우드에서 가장 중요한 프로젝트를 소개하고 각 프로젝트가 담당하는 영역을 알아봤다.
서비스 디스커버리, 분산 컨피규레이션, 서킷 브레이커 등의 패턴을 구현하기 위해 애플리케이션에 어떤 라이브러리를 포함할지 알게 된다.
애플리케이션 컨텍스트와 부트스트랩의 차이점도 알게 되었다.
릴리즈 트레인의 개념에 따라 프로젝트에서 의존성을 관리하는 방법을 배웠다.
컨설, 주키퍼, 래빗엠큐, 집킨 등 스프링 클라우드와 통합할 다양한 도구를 다룬 프로젝트를 확인했다.
다음 부분에서 스프링 클라우드를 사용해 분산 시트엠의 공통 패턴 구현을 담당할 하위 프로젝트에 대해 자세히 알아볼 것이다.
다음 장에서 서비스 레지스트리와 유레카 디스크버리 서버 솔루션부터 알아보자.
'MSA > 마스터링 스프링 클라우드' 카테고리의 다른 글
마스터링 스프링 클라우드 chap.4 (1) (0) | 2019.01.28 |
---|---|
마스터링 스프링 클라우드 chap.2 (0) | 2019.01.21 |
마스터링 스프링 클라우드 chap.1 (1) | 2019.01.09 |