본문 바로가기

엔지니어링(TA, AA, SA)/아키텍처

[MSA] 스프링 클라우드(1) - 개요

스프링 부트 프로젝트와 스프링 클라우드를 사용하면 반복적인 작업을 피하고 고품질의 안정적인 마이크로서비스 기반 분산 시스템을 빠르게 구축하고 적은 시간과 노력으로 시스템을 지속적으로 변화시킬 수 있다.

 

스프링 클라우드는 서비스 레지스트리(Service Registry)와 컨피규레이션 서버(configuration server), 서킷 브레이커(circuit breaker), 클라우드 버스(cloud bus), OAuth2 패턴, API 게이트웨이와 같은 마이크로서비스 기반 아키텍처에서 사용되는 모든 검증된 패턴을 구현한다. 모놀리식과 같은 전통적인 개발 방식을 사용하면 코드 베이스가 증가하고 수정과 유지보수가 아주 복잡해진다. 또한 새로운 기능과 프레임워크, 기술을 적용하는 것이 어려워지고 결국 새로운 아이디어를 적용하고 혁신하는데 부정적 영향을 미친다.

 

"네이티브 클라우드 애플리케이션이란 단순히 클라우드로 이전한 프로그램이 아니라 클라우드 환경을 위해 잘 설계된 프로그램이다."

 

새로운 모듈과 기능을 쉽게 확장할 수 있도록 마이크로서비스 아키텍처로 구성한다. 이제 이 시스템은 독립해서 빌드하고 실행하는 다수의 서비스로 구성되게 된다. 증가한 마이크로서비스의 수와 함께 시스템의 복잡도도 높아진다. 시스템 내부에서 서비스 Y 대신 서비스 X와 통신하는지 알 필요가 없는 외부의 API 클라이언트에게는 시스템의 복잡도를 숨길 것이다.

 

게이트웨이는 클라이언트의 모든 요청을 다양한 API 종단점으로 "동적으로 전달(서비스 디스커버리의 목록에 기반)"한다. API 게이트웨이가 특정 서비스 호출을 숨기거나 동적 라우팅 기능만 하는 것은 아니다. API 게이트웨이는 시스템으로의 진입점이기 때문에 중요한 데이터를 추적하거나 요청 메트릭을 수집하고 통계를 내기위한 좋은 장소가 될 수 있다. 또한 시스템 내 애플리케이션이 유용하게 사용할 부가정보를 삽입하기 위해 요청 및 응답 헤더를 조작할 수도 있다.

 

"N의 독립적인 마이크로서비스는 API 게이트웨이를 통해 외부 클라이언트로 숨겨지게 된다."

 


서비스 디스커버리의 필요성

모놀리식 애플리케이션을 독립적인 서비스 단위로 분리했다고 가정한다. 이 시스템은 복잡도를 API 게이트웨이 뒤로 숨겼기 때문에 외부에서 보면 전과 같아 보인다. 마이크로서비스는 앞으로 더 많아질 수 있고 서비스간 상호작용을 해야 한다. 이는 각 마이크로서비스가 상대방의 네트워크 주소 정보를 유지해야 한다는 뜻이다.

 

서비스 디스커버리는 컴퓨터 네트워크상의 디바이스가 제공하는 디바이스와 서비스를 자동으로 감지하는 서비스다. 

 

마이크로서비스 기반 아키텍처의 경우, 이것은 필수 메커니즘이다. 모든 서비스는 시작 후 다른 서비스가 접근할 수 있는 하나의 중앙 장소에 자신을 등록한다. 등록 키는 전체 시스템에서 유일한 서비스이거나 유일한 식별자여야 하는데, 이름을 통해 서비스를 찾고 호출하기 위해서다.

 

모든 개별키에는 할당된 값이 있다. 대부분의 경우 이 값은 서비스의 네트워크 위치를 나타낸다. 이러한 값들은 마이크로서비스의 여러 인스턴스 중 하나를 가리키는데, 아미크로서비스가 다른 머신이나 포트에서 실행되는 여러 독집적인 애플리케이션일 수 있기 때문이다.

 

하나의 키에 같은 서비스의 여러 인스턴스가 등록되는것 역시 가능하다. 뿐만 아니라 각 서비스는 특정 디스커버리 서버에 등록된 다른 서비스의 전체 목록을 얻는다. 아울러 각 마이크로서비스는 등록 목록의 변경 사항도 알아야 한다. 해당 정보는 각 마이크로서비스가 원격 디스커버리 서버에 의해 이전에 수집된 컨피규레이션을 주기적으로 갱신함으로써 얻을 수 있다.

 

서비스 디스커버리와 서버 컨피규레이션의 접근 방식은 매우 비슷하다. 서버 컨피규레이션 기능은 시스템 내 모든 컨피규레이션 파일을 중앙에서 관리할 수 있도록 한다. 일반적으로 이러한 컨피규레이션은 REST 웹서비스를 제공하는 서버가 된다. 각 마이크로서비스는 프로세스가 시작할때 컨피규레이션 서버에 접속해 자신을 위한 입력값을 얻어오려고 시도하게 된다.

 


서비스 간 통신

시스템의 신뢰성을 보장하려면 각 서비스가 하나의 인스턴스로만 운영되게 하면 안된다. 같은 서비스의 여러 인스턴스는 들어오는 요청에 대해 부하 분산을 적용해야 한다. 우선, 부하 분산기는 대개 API 게이트웨이에 내장돼 있다. 이 부하 분산기는 디스커버리 서버에 등록된 인스턴스 목록을 가져와야 한다. 특별한 이유가 없다면 유입되는 트래픽을 50/50으로 해서 모든 실행 중인 인스턴스에 분배하는 라운드 로빈(round-robin) 규칙을 적용한다. 이와 같은 규칙이 마이크로서비스 측의 부하 분산기에도 적용된다.

 

대개 마이크로서비스라고 하면 JSON 표기법을 사용하는 RESTful 웹서비스로 구성된다. 일대일 상호작용의 경우 유입되는 모든 요청이 정확하게 하나의 서비스 인스턴스에 의해 처리되는 반면, 일대다의 경우 다수의 서비스 인스턴스에 의해 처리된다.

 

가장 많이 사용하는 분류 기준은 호출이 동기 방식인지 비동기 방식인지다. 비동기 통신은 알림으로 구분할 수 있다. 클라이언트가 서비스에 요청을 보낼때 응답을 즉시 받을 필요가 없으며 스레드를 점유하지 않고 나중에 응답하는 비동기 호출로 수행할 수 있다.

 

스프링5부터 리액티브 마이크로서비스 타입 프로그래밍을 지원하고 있다. MongoDB나 Cassandra와 같은 NoSQL 데이터베이스와 리액티브 방식으로 통신을 지원하는 라이브러리가 있다.

 

그리고 잘알려진 통신 타입으로 게시-구독(publish-subscribe)가 있다. 이것은 일대다 통신 타입으로 클라이언트가 메시지를 발행하면 수신 대기 중인 모든 서비스에 의해 메시지가 소비된다. 일반적으로 이 모델은 Apache Kafka나 RabbitMQ, ActiveMQ와 같은 메시지 브로커로 구성된다.

 


장애와 서킷 브레이커

서비스 디스커버리, API 게이트웨이, 컨피규레이션 서버와 같은 메커니즘은 신뢰성이 높고 효율적인 시스템을 구성하도록 도와주는 유용한 요소다. 그러나 시스템 아키텍처를 설계할 때 이러한 다양한 측면을 고려했다고 하더라도 항상 장애에 대비해야 한다.

 

대부분 장애의 발생 원인은 네트워크 또는 데이터베이스의 문제와 같이 관리의 범위를 벗어난다. 이러한 에러를 처리하는 가장 좋은 방법은 응답을 기다릴때 네트워크 타임아웃을 활용하는 것이다. 한 서비스의 성능에 문제가 있으면 다른 서비스에 영향을 최소화하도록 노력해야 한다. 장시간 응답을 기다려서 스레드를 점유하게 하는 대신 에러 응답을 보내는 것이 낫다.

 

네트워크 타임아웃 문제에 대한 해결책은 circuit breaker pattern일 수 있다. 이 개념은 마이크로서비스의 접근 방식과 밀접하게 관련돼 있다. 서킷 브레이커는 성공 및 실패 요청의 횟수를 센다. 에러의 비율이 가정된 임계치를 넘으면 차단이 발생하고 이후의 시도는 즉시 실패한다. 지정된 기간이 지난 후 API 클라이언트는 요청을 다시 시작하고 성공하면 서킷이 닫혀 정상화된다. 서비스마다 사용할 수 있는 다수의 인스턴스가 있고 그중 한 인스턴스가 다른것보다 느리게 동작한다면 부하 분산 처리시 그 인스턴스는 무시된다.

 

네트워크 분리 장애에 자주 사용되는 메커니즘은 fallback이다. 이것은 요청이 실패했을때 수행되는 로직이다. 서비스가 캐싱된 데이터나 기본값, 빈 결과 목록을 반환할 수 있다. 캐싱된 데이터 또는 기본값을 반환하는 것보다는 에러코드를 전파하는 것이 더 나은 방법이다.

 


스프링 클라우드

스프링 클라우드의 가장 큰 장점은 모든 패턴과 메커니즘을 지원한다는 것이다. 마이크로서비스는 태생적으로 클라우드 네이티브다. 스프링 부트와 스프링 클라우드와 같은 프레임워크를 사용하면 클라우드 네이티브 개발을 가속할 수 있다. 마이크로서비스는 작고 독립적인 단위이기는 하지만 중앙에서 관리된다. 즉, 네트워크 위치, 컨피규레이션, 로깅 파일, 메트릭과 같은 정보는 중앙의 장소에 저장돼야 한다. 

 

The Twelve-Factor App이라는 흥미로운 initiative를 통해, 확장이 가능하고 쉽게 클라우드 플랫폼에 배포할 수 있으며 지속 배포 프로세스에 따라 배포되는 Software as a Service(SaaS)를 개발하는 방법론에 접근할 수 있다. 스프링 부트와 스프링 클라우드는 12-Factors Rule에 부합하는 애플리케이션을 만드는 기능과 요소를 제공한다. (https://12factor.net/ko/)

 

최근 분산 시스템이 제공하는 전형적인 기능은 대부분의 고유한 아키텍처를 갖는 프레임워크에서 제공되는데, 스프링 클라우드도 마찬가지다.

"분산/버전 컨피규레이션", "서비스 등록 및 디스커버리", "라우팅", "서비스 간의 호출", "부하 분산", "서킷 브레이커", "분산 메시징"

 

컨피규레이션은 YAML이나 application 또는 application-{profile} 이름의 properties 파일로 제공돼야 한다. 표준 스프링 부트 애플리케이션과 달리 스프링 클라우드는 원격 서버에서 컨피규레이션을 가져온다. 이를 위해 부트스트랩 컨텍스트에 애플리케이션 내에 필요한 최소 설정(애플리케이션 이름과 컨피규레이션 서버 주소 등)을 통해 스프링 클라우드 프로젝트가 외부 소스에서 컨피규레이션을 읽어올 수 있도록 한다. 

 

부트스트랩 컨텍스트는 메인 애플리케이션 컨텍스의 부모(parent)인데, application.yml 대신 bootstrap.yml을 사용한다. 일반적으로 애플리케이션 이름과 Spring Clound Conifg 설정은 다음과 같이 입력한다.

spring:
    application:
        name: person-service
    cloud:
        config:
           uri: http://192.168.99.100:8888

 

부트스트랩 컨텍스트를 비활성화하려면 설정 파일에서 spring.cloud.bootstrap.enabled 속성을 false로 설정한다. 부트스트랩 컨피규레이션 파일의 이름은 spring.cloud.bootstrap.name 속성으로 변경가능하고 spring.cloud.bootstrap.location 설정으로 설정 파일의 위치를 변경할 수 있다. 프로파일 메커니즘도 가능한데, bootstrap-development.yml 파일을 생성하면 development 프로파일이 활성화될때 이 파일이 로딩된다. 이러한 기능은 프로젝트 클래스 경로에 부모 의존성이 등록될때 자동으로 포함되는 스프링 클라우드 컨텍스트 라이브러리에서 사용할 수 있다.

 

스프링 클라우드 프로젝트에 부모 의존성으로 포함된 라이브러리는 Spring Cloud Commons이고, 서비스 디스커버리, 부하 분산, 서킷 브레이커 등의 메커니즘을 위한 공통의 추상 레이어를 제공한다. 이것은 @EnableDiscoveryClient 또는 @LoadBalanced 등의 자주 쓰이는 어노테이션을 포함한다.

 


Netflix OSS

개발자에게 넷플릭스가 유명한 이유는 바로 마이크로서비스 때문이다. 넷플릭스는 모놀리식 애플리케이션 기반의 전통적인 개발 모델에서 클라우드-네이티브 마이크로서비스 기반 개발방식으로 전환한 선구자다. 그 아키텍처 개념이 아주 성공적이어서 다른 대규모 조직의 롤모델이 되었다. 그들의 솔루션 라이브러리 기반의 수많은 오픈소스 프레임워크가 공개되었는데, 스프링 클라우드도 다르지 않아서 넷플릭스의 유명한 오픈소스 기능인 유레카(Eureka), 히스트릭스(Hystrix), 리본(Ribbon), 주울(Zuul) 등과 통합됐다.

 

"우리(넷플릭스)가 넷플릭스의 모든 것을 클라우드로 옮길 것이라고 했을때, 모두가 완전히 미쳤다고 했다. 그들은 우리가 실제로 해냈다고 믿지 않고 꾸며낸 것이라고 생각했다."

 


1) 유레카를 사용한 서비스 디스커버리

스프링 클라우드 넷플릭스에서 제공되는 첫 패턴은 유레카로 제공되는 서비스 디스커버리이다. 이 패키지는 클라이언트와 서버로 구분된다.

 

유레카 클라이언트를 프로젝트에 포함하려면 spring-cloud-starter-eureka 스타터를 사용한다. 클라언트는 항상 애플리케이션의 일부로 원격의 디스커버리 서버에 연결하는 일을 담당한다. 일단 연결되면 서비스 이름과 네트워크 위치를 담은 등록 메시지를 보낸다. 현재 마이크로서비스가 다른 마이크로서비스의 종단점을 호출해야 할 경우, 클라이언트는 서버로부터 등록된 서비스 목록을 담은 최신의 컨피규레이션을 가져오게 된다.

 

서버는 독립적인 스프링 부트 애플리케이션으로 설정되고 실행되는데, 각 서버의 상태를 다른 서버에 복제해 가용성이 높다. 유레카 서버를 프로젝트에 포함하려면 spring-cloud-starter-eureka-server 스타터를 사용한다.

 

2) 주울을 사용한 라우팅

스프링 클라우드 넷플릭스 프로젝트에 사용할 수 있는 패턴은 주울(Zuul)을 사용한 현명한 라우팅이다. 주울 라우팅 방식은 JVM 기반의 라우터이며 서버 측 부하분산과 일부 필터링을 수행한다. 주울은 폭넓은 곳에 적용할 수 있다. 넷플릭스에서는 주울을 인증이나 부하 평균 분배(Round-Robin), 정적 응답 처리, 부하 테스트에 사용한다. 주울은 설정가능하고 독립적인 스프링 부트 애플리케이션으로 실행된다는 점에서 유레카 서버와 같다.

 

주울을 프로젝트에 포함하려면 spring-cloud-starter-zuul 스타터를 사용한다. 마이크로서비스 아키텍처에서 주울은 전체 시스템의 진입점을 제공하는 API 게이트웨이로서 중요한 역할을 한다. 이를 위해 주울은 각 서비스의 네트워크 위치 정보를 알아야 하므로 유레카 서버와 통신하기 위해 디스커버리 클라이언트를 클래스 경로에 포함한다.

 

3) 리본을 사용한 부하 분산

스프링 클라우드 넷플릭스의 기능 중 클라이언트 측 부하 분산기인 리본(Ribbon)이 있다. 이것은 TCP, UDP, HTTP 등 가장 유명한 프로토콜을 지원하다. 동기 방식의 REST 호출뿐만 아니라 비동기 똔느 리액티브 모델도 지원한다. 부하 분산 외에도 서비스 디스커버리, 캐싱, 일괄 처리, 장애 내성과 통합할 수 있다. 리본은 기본 HTTP와 TCP 클라이언트를 한단계 더 추상화한다.

 

프로젝트에 포함하려면 spring-cloud-starter-ribbon 스타터를 사용한다. 리본은 라운드 로빈, 가용성 필터링, 응답 시간에 가중치를 두어 부하 분산을 하는 등의 규칙을 즉시 제공하고 사용자 정의 규칙을 쉽게 확장할 수 있다. 리본은 이름 기반 부하 분산을 하는 named client 개념에 기반한다. 

 

4) 자바 HTTP 클라이언트 작성하기

Feign은 넷플릭스 OSS 패키지 중 인기가 떨어지는 편이다. 이것은 선언적 REST 클라이언트로, 웹서비스 클라이언트를 쉽게 작성하도록 도와준다. Feign을 사용하면 개발자가 어노테이셔을 선언하기만 하면 애플리케이션이 실행될때 실제 구현이 실행된다.

 

Feign을 프로젝트에 추가하려면 spring-cloud-starter-feign 스타터를 사용한다. 이것은 리본 클라이언트와 통합돼 디스커버리 서비스와 통신, 부하 분산 같은 리본의 기능을 기본으로 제공한다.

 

5) 히스트릭스를 사용해 대기 시간 및 장애 내성 다루기

스프링 클라우드에는 서킷 브레이커 패턴을 구현한 라이브러리가 있다. 이것은 넷플릭스에서 서킷 브레이커 패턴을 구현한 히스트릭스 패키지에 기반한다. 히스트릭스는 기본적으로 Ribbon과 Feign 클라이언트를 통합할 수 있다. fallback은 서킷 브레이커 개념과 매우 밀접한 관련이 있다. 스프링 클라우드 라이브러리를 사용하면 서킷 브레이커 시간만료(timeout)가 발생했을때 실행돼야 하는 폴백 로직을 쉽게 설정할 수 있다. 히스트릭스를 프로젝트에 추가하려면 spring-cloud-starter-hystrix 스타터를 사용한다.

 

6) 아카이우스를 사용한 컨피규레이션 관리

스프링 클라우드 넷플릭스 프로젝트에서 마지막으로 중요한 기능은 아카이우스(archaius)다. 스프링 클라우드는 Apache Commons Configuration Project의 확장인 아카이우스를 참조한다. 이것은 변경 전의 원본을 가져오거나 변경사항을 클라이언트에 전달하는 방법으로 컨피규레이션을 갱신한다.

 


디스커버리와 분산 컨피규레이션

서비스 디스커버리와 분산 컨피규레이션 관리는 마이크로서비스 아키텍처에서 중요한 부분이다. 이 서로 다른 메커니즘은 기술적으로 매우 비슷하게 구현(결국 키-값 저장소에 특정 키와 값을 저장하는 방식)된다. 스프링 클라우드만의 한가지 특징은 분산 설정 기능을 직접 구현했다는 것이다. 이 기능은 스프링 클라우드 Config 프로젝트에 있다. 반대로 스프링 클라우드 서비스 등록 및 디스커버리를 위해서는 직접 구현한 것이 없다.

 

일반적으로 이 프로젝트는 서버 측과 클라이언트 측 지원으로 나눈다. 서버는 단 하나의 중앙의 장소로, 애플리케이션을 위한 모든 외부 속성이 모든 환경에 대해 서버에서 관리된다. 컨피규레이션은 여러 버전과 프로파일로 동시에 유지된다.

 

설정 파일은 파일 시스템 똔느 서버 클래스 경로에 있을 수도 있다. 또는 볼트(Vault)를 백엔드로 사용할 수 있다. 볼트는 토큰이나 패스워드, 자격 증명을 관리할 수 있는 해시코프(HashiCorp)에서 만든 오픈소스 도구이다. 일반적으로 볼트를 이용하면 컨피규레이션 서버의 접근 레벨을 안전하게 관리할 수 있다. 속성 저장소 백엔드가 무엇이든 스프링 클라우드 컨피그 서버의 HTTP와 리소스 기반 API를 통해 속성에 쉽게 접근할 수 있다. 이 API는 기본 인증으로 보호된다. 그러나 개인키/공개키 인증을 사용한 SSL 연결도 설정할 수 있다.

 

컨피그 서버는 REST API에 속성을 노출하는 독립된 스프링 부트 애플리케이션으로 실행된다. 프로젝트에 spring-cloud-config-server 의존성을 추가해 활성화한다. 또한 컨피규레이션 서버에 접속할 수 있는 클라이언트 라이브러리도 지원한다. 컨피규레이션 서버를 속성 저장소로 사용하는 모든 마이크로서비스 클라이언트는 클라이언트가 시작되고 스프링 빈이 생성되기 전에 컨피규레이션 서버에 접속한다. 클라이언트 측에서 클라우드 컨피그 클라이언트를 활성화하려면 프로젝트에 spring-cloud-config-starter 의존성을 포함한다.

 

 

아파치 주키퍼

스프링 클라우드가 지원하는 것은 아파치 주키퍼(Zookeeper)이다. 문서에 따르면 주키퍼는 컨피규레이션과 이름을 유지하는 중앙서비스로의 분산 동기화, 그룹 서비스를 가능하게 한다. 컨설에 적용되는 스프링 클라우드와 관련된 모든 것이 주키퍼에도 적용된다. 간단한 공통 어노테이션을 통한 통합제공, 설정 파일의 속성을 통한 컨피규레이션, 리본 또는 주울과 상호작용하기 위한 자동-컨피규레이션 등이 있다.

 

클라이언트 측에 주키퍼를 사용한 서비스 디스커버리를 사용하려면 spring-cloud-starter-zookeeper-discovery와 아파치 큐레이터를 의존성에 포함한다. 큐레이터는 통합을 쉽고 믿을 만하게 해주는 API 프레임워크와 유틸리티를 제공한다. 분산 컨피규레이션 클라이언트를 활성화하기 위해서는 spring-cloud-starter-zookeeper-config 의존성을 프로젝트에 추가한다.

 


슬루스(Sleuth)를 사용한 분산 추적

스프링 클라우드의 필수 기능 중 하나는 분산 추적이다. 이것은 스프링 클라우드 슬루스(Sleuth) 라이브러리가 구현한다. 분산 추적의 가장 중요한 목표는 하나의 요청을 여러 마이크로서비스로 처리할 때 이어지는 요청을 연관 짓는 것이다. 대부분의 경우는 HTTP 헤더에 기반한 메커니즘으로 추적을 구현한다. 이것은 Slf4j와 MDC로 개발되었다. Slf4j는 로그백이나 log4j., java.util.logging 등과 같은 특정 로깅 프레임워크의 추상화 퍼사드를 한다. MDC(mapped diagnostic context)는 다양한 소스의 로그 출력을 구분하고 실제 범위에 없던 부가 정보를 추가하는 솔루션이다.

 

스프링 클라우드 슬루스는 트레이스(trace) ID와 스팬(span) ID를 Slf4j MDC에 추가해 트레이스(trace) 또는 스팬(span)으로 모든 관련된 로그를 추출할 수 있다. 그리고 애플리케이션 이름이나 내보낼 수 있는 플래그 등의 다른 항목을 추가한다. 이것은 스프링 REST 템플릿이나 Feign 클라이언트, Zuul 필터, Hystrix, Spring Integration message Channel 등의 가장 유명한 메시징 솔루션과 통합된다. 이것은 RxJava나 스케줄 된 태스크와도 함께 쓰일 수 있다. 활성화하려면 프로젝트에 spring-cloud-starter-sleuth 의존성을 추가한다. 기본 스팬 및 트레이스 ID 메커니즘은 개발자에게 완전히 투명하다.

 

스프링 클라우드 Slueth는 추적을 위한 헤더 정보를 추가하는 것뿐만 아니라 지연 분석을 위한 기간 정보도 기록한다. 이 통계 정보는 시간 정보를 질의하고 시각화 하는 Zipkin 도구에 제공할 수 있다.

Zipkin은 마이크로서비스 아키텍처 내부의 지연 문제를 분석하기 위해 설계된 분산 추적 시스템이다. 이것은 입력 데이터를 수집하기 위한 HTTP 종단점을 노출한다. Zipkin으로 추적 데이터를 생성해 보내려면 spring-cloud-starter-zipkin 의존성을 프로젝트에 추가하면 된다.

 

모든 데이터를 분석할 필요가 없는 경우도 있다. 입력 트래픽 양이 너무 클때는 일부 데이터만 수집해야 한다. 이를 위해 스프링 클라우드 슬루에는 샘플링 정책이 있다. 즉, 집킨으로 보낼 트래픽의 양을 결정할 수 있다. 데이터 크기에 대한 솔루션으로 기본 HTTP 종단점 대신 메시지 브로커에 통계정보를 보내는 방법도 존재한다. 프로젝트에 spring-cloud-sleuth-stream 의존성을 추가하면 기능이 활성화되고 애플리케이션은 아파치 카프카나 래빗엠큐로 메시지를 보내는 producer가 된다.

 


메시징과 통합

일반적으로 스프링 클라우드는 동기/비동기 HTTP 통신과 메시지 브로커를 지원한다. 이 영역의 최숭선 프로젝트는 스프링 클라우드 버스다. 이것을 통해 컨피규레이션 속성 변경이나 다른 관리 명령 등의 상태 변경을 broadcast event로 애플리케이션에 알릴 수 있다. RabbitMQ나 Apache Kafka를 사용하는 AMQP 스타터를 사용할 수도 있지만, 일반적으로 spring-cloud-starter-bus-amqp 또는 spring-cloud-starter-bus-kafka 의존성만 추가하면 되고 기타 필요한 것은 자동-컨피규레이션을 통해 수행된다.

 

스프링 클라우드 버스는 다소 작은 프로젝트인데, 컨피규레이션 변경 이벤트의 ㅈ너달 등 공통 오퍼레이션을 위한 분산 메시징 기능을 사용할 수 있다. 메시지 중심 마이크로서비스로 구성된 시스템을 개발하기 위한 올바른 프레임워크는 스프링 클라우드 스트림이다.

 

스프링 클라우드 버스와 마찬가지로 스프링 클라우드 스트림에는 두 개의 바인더가 있다. 하나는 RabbitMQ를 사용하는 AMQP, 다른 하나는 Apache Kafka이다. 스프링 클라우드 스트림은 스프링 프로젝트의 또 다른 대형 프로젝트 중 하나인 Spring Integration에 기반한다. 이것은 종단점, 채널, aggregator, transformer와 같은 대부분의 엔터프라이즈 통합 패턴을 지원하는 프로그래밍 모델을 제공한다.

 

전체 마이크로서비스 시스템 내의 애플리케이션은 스프링 클라우드 스트림 입력 및 출력 채널을 통해 통신한다. 주된 통신 모델은 Pub/Sub으로 메시지가 공유된 토픽을 통해 전파된다. 아울러 모든 마이크로서비스의 다중 인스턴스 지원도 중요하다. 대부분 메시지는 하나의 인스턴스에서 처리돼야 하는데, Pub/Sub 모델에서는 지원하지 않는다. 이것이 스프링 클라우드 스트림에서 grouping 메커니즘을 만든이유다. 메시지는 목적지 그룹의 오직 한 멤버만 수신한다. (spring-cloud-starter-stream-kafka 또는 spring-cloud-starter-stream-rabbit 의존성을 추가함으로써 기능 적용이 가능)

 


스프링 클라우드는 수많은 서로 다른 도구와 솔루션의 통합을 제공하는 다수의 하위 프로젝트로 구성된다. 아래는 스프링 클라우드 프로젝트를 범주에 따라 구분한 다이어그램이다.

 

스프링 클라우드 내에는 수많은 프로젝트가 있고 프로젝트 간의 관계도 많다. 프로젝트는 모두 다른 릴리즈 주기와 버전 번호를 갖는 독립적인 프로젝트다. 이런 상황에서 애플리케이션의 의존성 관리는 문제가 될 수 있고 모든 프로젝트 버전 간의 관계를 알아야 하는 문제가 있다. 이런 문제점을 쉽게 처리하기 위해 스프링 클라우드는 스타터 메커니즘과 릴리즈 트레인을 도입했다.

 

릴리즈 트레인은 하위 프로젝트의 혼란을 피하기 위해 릴리즈를 버전이 아닌 이름으로 구분한다. 런던 지하철 역의 이름에 따라 알파벳 순서로 사용한다. 첫 릴리즈는 엔젤이었고 둘째는 브릭스턴이었다. 의존성 관리의 전체 메커니즘은 BOM(Bill of materials)에 기반한다. 이것은 아티팩트 버전을 독립적으로 관리하는 표준 메이븐 개념이다. M[X]의 M은 마일스톤(milestone), X는 버전 번호를 나타내고 SR[X]는 서비스 릴리즈로서 중요한 버그를 수정한 버전을 나타낸다.

 

스프링 클라우드 스트림은 자신의 릴리즈 트레인을 가지고 있는데, 스프링 클라우드 프로젝트의 규칙과 동일하게 하위 프로젝트를 그룹으로 묶는다. (https://projects.spring.io/spring-cloud/)