보통 우리가 애플리케이션를 개발 시 코드에 상수나 특정 절대 경로를 하드코딩 하는 일은 거의 없다. 일반적으로 properties같은 환경 변수에 그것들을 관리하는데, 만약 프로퍼티가 변경될 경우에는 애플리케이션을 다시 배포하고는 한다.
특히, 클라우드 환경에서 같이 여러 인스턴스가 여러 개 실행되고 있는 경우에는 모든 애플리케이션을 재실행해야 하는 경우가 생긴다.
Spring Cloud Config는 클라우드 환경에서 MSA 애플리케이션을 작성하고 여러 서버에 인스턴스들을 실행시킬 경우 애플리케이션과 구성정보를 중앙저장소(Git)에 저장하고 애플리케이션과 완전히 분리시킬 수 있게 해준다. 모든 애플리케이션 인스턴스는 가동 시 중앙저장소에서 구성정보를 읽어오며, Property 변경 시 중앙저장소로부터 다시 구성 정보를 읽어올 수 있도록 한다.
Spring Cloud Confnig는 크게 두 가지 구성 요소가 존재한다.
1. Git 과 같은 형상 관리 툴로 백업되어 application의 설정을 관리해주는 Spring Cloud Config Server
2. application이 Spring Cloud Config Server에 접근할 수 있도록 도와주는 Spring Cloud Config Client
(위 그림에서 각 MicroService)
클라이언트는 Config 서버로 설정값을 요청하면 서버는 설정 파일이 위치한 원격 Git repo에 접근한다.
서버는 Git으로부터 최신 설정 값을 받아 클라이언트에게 전달한다. 만약, 사용자가 설정 파일을 변경하여 Git에 반영했다면 클라이언트의 엔드포인트인 actuator/refresh
엔드포인트를 호출하여 설정값을 변경하도록한다.
java 8
Gradle 6.8.3
Spring Boot 2.5.6
모듈 구조는 multimodule 구조로 구성했다. (서비스들은 추가될 예정)
📦spring-cloud-with-msa
┣ 📂apigateway
┣ 📂config
┣ 📂discovery-service
┣ 📂first-service
┣ 📂second-service
┣ 📂user-service
┣ 📜build.gradle
┣ 📜gradlew
┣ 📜gradlew.bat
┗ 📜settings.gradle
멀티 모듈 환경에서 작업하기 위해 sub project들의 중복 의존성을 상위 build.gradle에서 한 번 정의해주었다.
spring cloud는 spring boot 버전에 따라 지원하는 버전이 상이하다. 잘 확인 후 알맞게 기입하자.
(Spring Cloud)
Release Train | Boot Version |
---|---|
2021.0.x aka Jubilee | 2.6.x |
2020.0.x aka Ilford | 2.4.x, 2.5.x (Starting with 2020.0.3) |
Hoxton | 2.2.x, 2.3.x (Starting with SR5) |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
buildscript {
ext {
springBootVersion = '2.5.6'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE")
}
}
subprojects {
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'java'
group = 'com.shinmj'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
//actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator:2.1.8.RELEASE'
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-bootstrap', version: '3.0.4'
}
}
(출처 : Spring Cloud Config Server | 토리맘의 한글라이즈 프로젝트)
Version Control Backend FileSystem Use
VCS(SVN, GIT) 기반을 사용하면 파일들을 로컬 시스템으로부터 Checkout 받는다. 기본적으로 config-repo-
프리픽스와 함께 임시 디렉토리에 저장하게 된다. 일부 운영체제는 정기적으로 이 임시 디렉토리를 정리하기 때문에 Property가 유실될 수도 있다. 이를 방지 하기 위해 spring.cloud.config.server.git.basedir
(또는 spring.cloud.config.server.svn.basedir)를 사용하여 시스템 임시 구조에 속하지 않는 디렉토리로 설정해 컨피그 서버에서 사용할 디렉토리로 변경한다.
File System Backend
Config Server에서는 Git을 사용하지 않고 로컬 classpath나 filesysytem에서 설정 파일을 로드하는 “native” 프로파일도 존재한다. 이 native 프로파일을 사용하려면 config server를 spring.profiles.active=native로 시작하면 된다.
그리고 spring.cloud.config.server.native.searchLocations
로 정적 URL을 가리키도록 하면 된다. 파일 리소스에는 file:
prefix를 붙여야 하며(prefix가 없을 때 기본 값은 보통 classpath이다.) 다른 spring boot 설정과 마찬가지로 ${}
스타일의 enviroment 플레이스홀더를 포함할 수 있지만, Windows의 절대 경로에는 /
가 추가로 하나 더 필요하다(ex)file:///${user.home}/config-repo)
이 방식은 빠르게 테스트해보고 시작하는데 적합하다. 프로덕션에서 사용하려면 신뢰할 수 있다.
Spring Config Service 자체도 eureka service의 client로써 등록되어야 하기 때문에 관련 의존성을 추가해준다.
ext {
set('springCloudVersion', "2020.0.5")
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//config
implementation 'org.springframework.cloud:spring-cloud-config-server'
// eureka
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client', version: '3.0.4'
}
EnableConfigServer 어노테이션을 등록해준다.
@SpringBootApplication
@EnableConfigServer
public class ConfigServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServiceApplication.class);
}
}
server:
port: 8888
spring:
application:
name: config-service
cloud:
config:
server:
git:
uri: https://github.com/ShinMyeongJi/spring-cloud-with-msa.git
basedir: config
search-paths: dev, stg, prod
default-label: main
management:
endpoints:
enabled-by-default: false
endpoint:
info:
enabled: true
8888
이다.spring.cloud.server.git.uri
를 통해 원격 레포지토리와 연결할 수 있다.baseDir
은 각 환경변수 파일들이 저장될 폴더명이다.search-paths
는 환경변수들의 profiles를 구분하기 위한 sub folder이다.label
은 branch를 찾기 위한 옵션이다. 보통 git repo 생성시 default branch는 main이기 때문에 다음과 같이 설정해주었다.다음은 각 config들이 포워딩 될 Service들을 추가해준다. 이것들은 msa에서 평범하게 추가되는 service들이며 각각 Config Server를 통해 관리된다.
모듈 상위에 First-Service 모듈을 추가하고 다음과 같은 의존성을 설정한다.
build.gradle
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:3.0.4'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
이제 config service에서 설정한 basedir에 설정 파일을 추가해줄 것이다.
/config/dev/first-service-dev.yml
파일의 이름은 포워딩 될 {service이름}-{프로파일}.yml 형태로 맞춰야 한다.
일단 테스트를 위해 다음과 같이 설정한 뒤 git에 반영한다.
config:
name: dev
info:
description: Spring Cloud Dev
Config Server의 API를 통해 추가한 설정파일의 이름대로 엔드포인트로 접근한다.
host:port/{서비스-이름}/{프로파일}
그러면 Response로 설정한 properties들을 json 반환한다.