1. Spring Cloud Config란?
Spring Cloud Config는 분산 시스템에서 설정 정보를 중앙화된 외부 저장소에서 관리할 수 있게 해주는 Spring Cloud의 핵심 컴포넌트이다. Config Server는 Git, File System, Vault 등의 저장소에서 설정 정보를 가져와 각 마이크로서비스에 제공하며, 설정 변경시 서비스 재시작 없이 동적으로 적용이 가능하다. Config Client는 Config Server로부터 설정 정보를 가져와 사용하며, 이를 통해 모든 마이크로서비스의 설정을 한 곳에서 효율적으로 관리할 수 있다. 여러 환경(개발, 테스트, 운영)과 여러 서비스에 걸친 설정 관리를 단순화하고 일관성을 유지하는 데 도움을 준다.
2. 주요 기능
2 - 1. 중앙 집중식 구성 관리
모든 마이크로서비스의 설정을 중앙에서 관리한다.
2 - 2. 환경별 구성
개발, 테스트, 운영 등 환경별로 구성을 분리하여 관리할 수 있다.
2 - 3. 실시간 구성 변경
설정 변경시 애플리케이션을 재시작하지 않고도 실시간으로 반영할 수 있다.
3. 실시간 구성 변경
실시간 구성 변경을 반영하는 방법에는 여러 가지가 있다.
- Spring Cloud Bus를 사용하는 방법
- 수동으로 /actuator/refresh 엔드포인트를 호출하는 방법
- Spring Boot DevTools를 사용하는 방법
- Git 저장소를 사용하는 방법
Spring Cloud Bus는 메시징 시스템(RabbitMQ 또는 Kafka)을 통해 실시간으로 설정 변경 사항을 전파하는데 매우 유용하며, Git 저장소를 사용하면 설정 파일의 버전 관리를 쉽게 할 수 있고, Spring Boot DevTools는 주로 개발 환경에서 유용하게 사용된다.
4. 실습
Config Server를 통해 Port 정보와 message를 Config Server에서 가져온다.
Config Server의 message가 변경될 때, /actuator/refresh 엔드포인트를 호출하여 product 애플리케이션의 message가 갱신되는 모습을 확인한다.
5. Config Server
Config Server 도 Eureka Client 이다.
Config Server 이므로, Config Server dependency를 추가해준다.
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.6'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.spring-cloud.eureka.client'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
ext {
set('springCloudVersion', "2023.0.3")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-config-server'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
application.yml
server:
port: 18080
spring:
profiles:
active: native
application:
name: config-server
cloud:
config:
server:
native:
search-locations: classpath:/config-repo # 리소스 폴더의 디렉토리 경로
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
native 프로파일
로컬 파일 시스템에서 설정을 읽어올 때 사용하는 프로파일이다.
개발 환경이나 테스트 시에 주로 사용된다.
Git이나 외부 저장소에서 설정을 읽어올 때는 native 프로파일을 제거하고 Git, 또는 외부 저장소 관련 설정만 제공하면 된다.
아래 처럼
spring:
cloud:
config:
server:
git:
uri: [Git 저장소 URL]
clone-on-start: true
config Server는 기본적으로 Git 저장소를 사용하도록 설계되어 있다.
search-locations
설정 파일들이 위치한 경로를 지정한다.
classpath:/config-repo는 프로젝트의 resources 폴더 아래에 있는 config-repo 디렉토리를 의미한다.
로컬 파일 시스템에서 설정 파일을 읽어올 때 사용된다.
product-service.yml
server:
port: 19093
message: "product-service message"
product-service-local.yml
server:
port: 19083
message: "product-service-local message"
두 개 설정 파일을 만들어 줬다.
product-service에서 프로파일을 지정해주면 config 서버가 port랑 message를 주입해줄 것이다.
ConfigApplication
package com.spring_cloud.eureka.client.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
`@EnableConfigServer` 이게 있어야 Config Server로 동작한다.
6. product-service
build.gradle의 dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.cloud:spring-cloud-starter-config' // config-client
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
actuator가 있어야 /actuator/refresh 엔드포인트를 호출할 수 있다.
config-client로 설정해야 Config-Server가 설정을 넣어줄 수 있다.
application.yml
server:
port: 0 # 임시 포트, 이후 Config 서버 설정으로 덮어씌움
spring:
profiles:
active: local
application:
name: product-service
config:
import: "configserver:"
cloud:
config:
discovery:
enabled: true
service-id: config-server
management:
endpoints:
web:
exposure:
include: refresh
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
message: "default message"
port 를 0 으로 지정하여 Config Server에서 실제 포트를 할당 받는다.
cloud.config.discovery.enabled: true -> Eureka를 통한 Config Server 발견 활성화
profiles.active: local -> local 프로파일 활성화
management.endpoints.web.exposure.includ: refresh -> 설정 갱신을 위한 refresh 엔드포인트 활성화
message: "default message" -> 기본 메시지 설정, Config Server가 실제 메시지를 전달해준다.
ProductController
package com.spring_cloud.eureka.client.product;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @RefreshScope 애노테이션은 Spring 애플리케이션의 빈이 설정 변경을 반영할 수 있도록 하는 역할을 합니다.
* 기본적으로 Spring 애플리케이션의 빈은 애플리케이션이 시작될 때 초기화되고, 설정 값이 변경되더라도 해당 빈은 갱신되지 않습니다.
* 이 애노테이션을 사용하면 /actuator/refresh 엔드포인트를 호출하여 설정 변경 사항을 동적으로 반영할 수 있습니다.
*/
@RefreshScope
@RestController
@RequestMapping("/product")
public class ProductController {
@Value("${server.port}") // 애플리케이션이 실행 중인 포트를 주입받습니다.
private String serverPort;
@Value("${message}")
private String message;
@GetMapping
public String getProduct() {
return "Product detail from PORT : " + serverPort + " and message : " + this.message ;
}
}
`@RefreshScope`는 런타임에 애플리케이션의 설정을 동적으로 갱신할 수 있게 해주는 어노테이션이다.
`@RefreshScope`가 적용된 빈은 설정 변경시 새로운 인스턴스로 재생성된다.
/actuator/refresh 엔드포인트 호출시 설정이 갱신된다.
모든 빈에 해당 어노테이션을 적용하면 성능에 영향을 줄 수 있다.
동적 갱신이 필요한 빈에만 선택적으로 적용하는 것이 좋다.
7. Run
Eureka Server를 먼저 띄우고 Config Server도 띄운 후에 product-service를 띄운다.
local 프로파일이므로 Config Server가 포트를 19083으로 지정해준다.
메시지 확인
메시지가 local 프로파일에 맞게 들어왔다.
프로파일을 지정하지 않고 Run
Config Server가 Port를 19093으로 지정해줬다.
메시지 확인
local이 빠져있는 것을 확인할 수 있다.
Config Server의 product-service-local.yml의 메세지 갱신
server:
port: 19083
message: "product-service-local message update"
메세지에 "update"를 추가했다.
그리고 Config Server를 재시작한다.
/actuator/refresh 호출
message가 응답으로 받았는데, message가 바뀌었다는 의미다.
refresh 후 메세지 확인
"update" 문구가 추가된 것을 확인할 수 있다.
References
https://docs.spring.io/spring-cloud-config/reference/index.html
https://spring.io/projects/spring-cloud-config
https://www.geeksforgeeks.org/managing-configuration-for-microservices-with-spring-cloud-config/
'MSA' 카테고리의 다른 글
2024 11 29 TIL - 분산추적, Zipkin (2) | 2024.11.29 |
---|---|
2024 11 27 TIL - API Gateway, Spring Cloud Gateway (0) | 2024.11.27 |
2024 11 26 TIL - CircuitBreaker(Resilience4j) (0) | 2024.11.26 |
2024 11 25 TIL - 로드 밸런싱, Netflix Ribbon (0) | 2024.11.25 |
2024 11 22 TIL - Spring Cloud Netfilx Eureka로 알아보는 서비스 디스커버리 (3) | 2024.11.22 |