소개
이 글에서는 스프링 클라우드 알리바바(Spring Cloud Alibaba)의 사용법에 대해 다룹니다. 주로 알리클라우드 공식 홈페이지의 스프링 클라우드 알리바바 7일 트레이닝 캠프 내용과 예제를 기반으로 합니다.
스프링 클라우드 알리바바 분산 설정
네이커스(Nacos) 컨피그를 통한 분산 설정 구현
과정 개요
이 과정에서는 다음과 같은 내용을 학습합니다:
- 네이커스 컨피그를 스프링 클라우드 분산 설정으로 사용하는 방법
- 네이커스 컨피그를 이용한 빈(Bean) 동적 새로고침 구현
- 네이커스 컨피그 고급 설정 이해
프레임워크 소개
네이커스(Nacos)는 설정 및 기타 메타데이터를 저장하기 위한 key/value 저장소를 제공하며, 분산 시스템의 외부 설정에 대한 서버 측과 클라이언트 측 지원을 제공합니다. 스프링 클라우드 알리바바 네이커스 컨피그를 사용하면 네이커스 서버에서 스프링 클라우드 애플리케이션의 외부 속성 설정을 중앙 관리할 수 있습니다.
스프링 클라우드 알리바바 네이커스 컨피그는 컨피그 서버와 클라이언트의 대안으로, 클라이언트와 서버의 개념은 스프링 환경과 프로퍼티 소스(PropertySource)와 일관된 추상화를 가집니다. 특별한 부트스트랩 단계에서 설정이 스프링 환경로 로드됩니다.
세부 내용
이 튜토리얼은 다음 내용을 포함합니다:
- 빠른 시작: 코드 가져오기 또는 자신의 프로젝트에 네이커스 도입
- 다중 파일 확장자 지원: YAML 파일 확장자를 예로 들어 네이커스 컨피그 다중 파일 확장자 지원 설명
- 동적 설정 업데이트: @RefreshScope 특성을 사용하여 빈 동적 새로고침 구현
- 사용자 정의 확장: 네임스페이스, 그룹 및 데이터 ID의 설정 확장
- 운영 특성: 네이커스 컨피그 고급 외부 설정 및 엔드포인트 내부 세부 사항
준비 작업
이 섹션에서는 후속 작업을 위해 실험실에서 몇 가지 준비 작업을 수행합니다.
네이커스 서버 시작
다음 명령어를 사용하여 서버를 시작합니다:
sh ~/prepare.sh
다음 명령어로 네이커스 시작 로그를 확인할 수 있습니다:
cat /home/shell/nacos/logs/start.out
프로젝트 코드 다운로드
다음 명령어를 사용하여 이 과정에서 사용할 프로젝트 코드를 가져옵니다.
$cloudshell-git-open "https://start.aliyun.com/type=maven-project&language=java&architecture=none&bootVersion=2.3.7.RELEASE&baseDir=nacos-config-sample&groupId=com.alibaba.cloud&artifactId=nacos-config-sample&name=nacos-config-sample&description=Demo%20project%20for%20Spring%20Boot&packageName=com.alibaba.cloud.nacos-config-sample&packaging=jar&javaVersion=1.8&dependencies=sca-nacos-config,web/nacos-config-sample.git" /home/shell/nacos-config-sample
네이커스 컨피지를 도입하여 분산 설정 구현
이 섹션에서는 로컬 환경에 네이커스 컨피지를 도입하는 방법에 대한 안내를 제공합니다.
네이커스 컨피지 도입 방식
네이커스 컨피지 도입에는 알리윈 자바 이니셜라izr(Aliyun Java Initializr)를 통한 도입과 Maven pom.xml 의존성 추가의 두 가지 방식이 있습니다. 공식적으로는 컴포넌트 간 의존성 관계를 단순화하기 위해 네이커스 디스커버리(Nacos Discovery) 도입에 알리윈 자바 이니셜라izr 방식을 권장합니다.
프로젝트 스캐폴드를 통한 프로젝트 생성 및 네이커스 컨피지 도입(권장)
스프링 클라우드 컴포넌트 버전과 의존성이 복잡하므로, 애플리케이션 프로젝트 구축에 프로젝트 스캐폴드 사용을 권장합니다.
앞서 가져온 코드는 실제로 프로젝트 스캐폴드를 사용하여 생성되었습니다.
사용자는 선호하는 웹 브라우저로 프로젝트 스캐폴드에 접속합니다. 리소스 주소는 다음과 같습니다: https://start.aliyun.com/bootstrap.html
다음은 구글 크롬 브라우저를 예로 들어 설명합니다. 웹 페이지가 로드된 후, "프로젝트 기본 정보" 부분에 그룹(Group): "com.alibaba.cloud" 및 아티팩트(Artifact): "nacos-config-sample"을 입력합니다. 그런 다음 "컴포넌트 의존성" 입력 상자에서 "Nacos Config"를 검색하고 "Nacos Configuration", "Spring Web" 및 "Spring Boot Actuator" 컴포넌트를 선택합니다.
네이커스 컨피지를 사용한 분산 설정 구현
이 섹션에서는 프로젝트를 수정하여 네이커스 컨피지와 통합합니다.
네이커스 서버 접속
네이커스 콘솔(계정명/비밀번호: nacos/nacos)을 열고 "설정 관리/설정 목록"을 선택합니다.
네이커스 설정 추가
"설정 목록" 페이지 오른쪽의 "+" 버튼을 클릭합니다.
브라우저가 새 페이지로 이동하며 다음 내용으로 채웁니다:
Data ID: nacos-config-sample.properties
user.name=nacos.config.properties
user.age=99
여기서 데이터 ID는 애플리케이션 이름(nacos-config-sample)과 파일 확장자(.properties)로 구성됩니다. "발행" 버튼(빨간색 화살표)을 클릭하면 설정 내용이 다음과 같이 변경됩니다:
user.name=nacos-config-sample
user.age=90
발행이 성공하면 콘솔에 팝업 알림이 나타납니다.
애플리케이션 설정 수정
bootstrap.properties 파일을 엽니다.
레지스트리 주소를 방금 시작한 네이커스 서버 주소로 변경합니다.
application.properties 파일을 엽니다.
애플리케이션 서비스 포트를 60000으로 수정합니다.
로컬에서 작업하는 경우 다음과 같은 설정을 참조할 수 있습니다:
resources 디렉토리에 "bootstrap.properties"라는 이름의 파일을 새로 만들고 다음 내용을 구성합니다:
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
네이커스 서버 주소는 반드시 bootstrap.properties 파일에 구성해야 합니다.
네이커스 컨피지 읽기를 구현하는 코드 추가
다음 코드를 프로젝트에 추가하여 시작 시 네이커스의 설정 항목을 읽고 출력합니다:
package com.example.nacosconfigdemo;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class NacosConfigDemo {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@PostConstruct
public void init() {
System.out.printf("[초기화] 사용자 이름: %s, 나이: %d%n", userName, userAge);
}
}
네이커스 컨피지 애플리케이션 시작
먼저 프로젝트를 컴파일합니다:
cd /home/shell/nacos-config-sample && mvn clean package
최초 컴파일에는 1~3분이 소요될 수 있습니다.
컴파일이 완료되면 프로그램을 시작합니다:
java -jar /home/shell/nacos-config-sample/target/nacos-config-sample-0.0.1-SNAPSHOT.jar
시작이 완료되면 다음과 같은 로그가 표시되며, 이는 시작 과정에서 네이커스 서버의 설정 데이터를 읽었다는 것을 의미합니다:
[초기화] 사용자 이름: nacos-config-sample, 나이: 90
네이커스 컨피지를 사용한 빈 동적 새로고침 구현
네이커스 컨피지는 표준 스프링 클라우드 @RefreshScope 특성을 지원합니다. 즉, 애플리케이션이 특정 네이커스 설정을 구독한 후 설정 내용이 변경될 때 Refresh Scope Beans에 바인딩된 속성이 조건부로 업데이트됩니다.
조건이란 다음과 같습니다:
- 필수 조건: Bean의 선언 클래스에 @RefreshScope가 표시되어야 합니다.
- 둘 중 하나 조건:
- 속성(비 static 필드)에 @Value 표시
- @ConfigurationProperties Bean
除此之外, 네이커스 컨피지는 네이커스 클라이언트 하위 레이어 데이터 변경 리스너 인터페이스인 com.alibaba.nacos.api.config.listener.Listener도 도입했습니다.
@Value 속성에 대한 빈 동적 새로고침 구현
nacos-config-sample 애플리케이션을 기반으로 수정하여,引导 클래스 NacosConfigDemo에 @RefreshScope와 @RestController를 표시하여 해당 클래스가 스프링 MVC REST 컨트롤러가 되고 동적 새로고침 기능을 갖도록 합니다.
@RestController
@RefreshScope
public class NacosConfigDemo {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@PostConstruct
public void init() {
System.out.printf("[초기화] 사용자 이름: %s, 나이: %d%n", userName, userAge);
}
@PreDestroy
public void destroy() {
System.out.printf("[소멸] 사용자 이름: %s, 나이: %d%n", userName, userAge);
}
@RequestMapping("/user")
public String user() {
return String.format("[HTTP] 사용자 이름: %s, 나이: %d", userName, userAge);
}
}
@ConfigurationProperties Bean에 대한 속성 동적 새로고침 구현
애플리케이션 nacos-config-sample에 새로운 User 클래스를 추가하고 @RefreshScope와 @ConfigurationProperties를 표시합니다.
@RefreshScope
@ConfigurationProperties(prefix = "user")
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
네이커스 컨피지 리스너를 사용한 빈 속성 동적 새로고침 구현
com.alibaba.nacos.api.config.listener.Listener는 네이커스 클라이언트 API 표준의 설정 리스너 인터페이스입니다. 스프링 체계와 직접 연결될 수 없으므로, 스프링 클라우드 알리바바 네이커스 컨피지 API인 NacosConfigManager를 사용합니다.
@RefreshScope
@RestController
@EnableConfigurationProperties(User.class)
public class NacosConfigDemo {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@Autowired
private User user;
@Autowired
private NacosConfigManager nacosConfigManager;
@Bean
public ApplicationRunner runner() {
return args -> {
String dataId = "nacos-config-sample.properties";
String group = "DEFAULT_GROUP";
nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("[리스너] " + configInfo);
System.out.println("[변경 전] " + user);
Properties properties = new Properties();
try {
properties.load(new StringReader(configInfo));
String name = properties.getProperty("user.name");
int age = Integer.valueOf(properties.getProperty("user.age"));
user.setName(name);
user.setAge(age);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("[변경 후 사용자] " + user);
}
});
};
}
@PostConstruct
public void init() {
System.out.printf("[초기화] 사용자 이름: %s, 나이: %d%n", userName, userAge);
}
@PreDestroy
public void destroy() {
System.out.printf("[소멸] 사용자 이름: %s, 나이: %d%n", userName, userAge);
}
@RequestMapping("/user")
public String user() {
return String.format("[HTTP] 사용자 이름: %s, 나이: %d", userName, userAge);
}
@RequestMapping("/userObject")
public String userObject() {
return "[HTTP] " + user;
}
}
네이커스 컨피지 고급 설정
사용자 정의 네임스페이스 설정 지원
네이커스의 네임스페이스 개념은 테넌트 단위의 설정 격리를 위한 것입니다. 다른 네임스페이스에는 동일한 그룹 또는 데이터 ID의 설정이 존재할 수 있습니다. 네임스페이스의 일반적인 사용 시나리오 중 하나는 개발 테스트 환경과 프로덕션 환경의 리소스(예: 설정, 서비스) 격리 등입니다.
${spring.cloud.nacos.config.namespace} 설정을 명시적으로 지정하지 않은 경우 기본적으로 네이커스의 Public 네임스페이스를 사용합니다. 사용자 정의 네임스페이스를 사용하려면 다음 설정을 통해 구현할 수 있습니다:
spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7
사용자 정의 그룹 설정 지원
${spring.cloud.nacos.config.group} 설정을 명시적으로 지정하지 않은 경우 기본값은 DEFAULT_GROUP입니다. 사용자 정의 그룹을 사용하려면 다음 설정을 통해 구현할 수 있습니다:
spring.cloud.nacos.config.group=DEVELOP_GROUP
사용자 정의 확장 데이터 ID 설정 지원
스프링 클라우드 알리바바 네이커스 컨피지는 0.2.1 버전부터 사용자 정의 데이터 ID 설정을 지원합니다. 다음은 전체 설정 예시입니다:
spring.application.name=opensource-service-provider
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 외부 설정
# 1. 기본 그룹 DEFAULT_GROUP의 데이터 ID, 설정 동적 새로고침 미지원
spring.cloud.nacos.config.extension-configs[0].data-id=ext-config-common01.properties
# 2. 기본 그룹이 아닌 데이터 ID, 동적 새로고침 미지원
spring.cloud.nacos.config.extension-configs[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.extension-configs[1].group=GLOBALE_GROUP
# 3. 기본 그룹이 아니면서 동적 새로고침 지원
spring.cloud.nacos.config.extension-configs[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.extension-configs[2].group=REFRESH_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true
공유 설정
여러 애플리케이션 간 설정 공유 문제를 해결하고 하나의 애플리케이션에 여러 설정 파일을 지원하기 위해, 다음과 같은 방식으로 공유 데이터 ID를 더 명확하게 구성할 수 있습니다:
# 공유 데이터 ID 설정
spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml
# 데이터 ID가 속한 그룹 설정, 생략 시 DEFAULT_GROUP
spring.cloud.nacos.config.shared-configs[0].group=GROUP_APP1
# 데이터 ID 설정 변경 시 동적 새로고침 여부, 생략 시 false
spring.cloud.nacos.config.shared-configs[0].refresh=true
설정 우선순위
스프링 클라우드 알리바바 네이커스 컨피지는 현재 네이커스에서 관련 설정을 가져오는 세 가지 설정 기능을 제공합니다:
- A: spring.cloud.nacos.config.shared-configs[n].data-id를 통한 여러 공유 데이터 ID 설정
- B: spring.cloud.nacos.config.extension-configs[n].data-id를 통한 여러 확장 데이터 ID 설정
- C: 내부 관련 규칙(애플리케이션 이름, 애플리케이션 이름 + Profile)을 통해 자동으로 생성된 데이터 ID 설정
세 가지 방식을 함께 사용할 때 우선순위 관계는 A < B < C 입니다.
설정 완전 비활성화
spring.cloud.nacos.config.enabled = false를 설정하여 스프링 클라우드 네이커스 컨피지를 완전히 비활성화할 수 있습니다.
기타 고급 설정
| 설정 항목 | Key | 기본값 | 설명 |
|---|---|---|---|
| 서버 주소 | spring.cloud.nacos.config.server-addr | 네이커스 서버 시작 시 리스닝하는 IP 주소와 포트 | |
| 설정 데이터 ID | spring.cloud.nacos.config.name | prefix를 먼저 확인, 다음 name, 마지막으로 spring.application.name | |
| 설정 데이터 ID | spring.cloud.nacos.config.prefix | prefix를 먼저 확인, 다음 name, 마지막으로 spring.application.name | |
| 설정 내용 인코딩 | spring.cloud.nacos.config.encode | 읽은 설정 내용에 해당하는 인코딩 | |
| 그룹 | spring.cloud.nacos.config.group | DEFAULT_GROUP | 설정에 해당하는 그룹 |
| 파일 확장자 | spring.cloud.nacos.config.fileExtension | properties | 설정 항목에 해당하는 파일 확장자, 현재 properties와 yaml(yml) 지원 |
| 설정 가져오기 시간 초과 | spring.cloud.nacos.config.timeout | 3000 | 클라이언트 설정 가져오기 시간 초과(밀리초) |
네이커스 컨피지 액추에이터 엔드포인트
네이커스 컨피지는 내부적으로 엔드포인트를 제공하며, 해당 엔드포인트 ID는 nacos-config이고 액추에이터 웹 엔드포인트 URI는 /actuator/nacos-config입니다.
엔드포인트가 노출하는 JSON에는 세 가지 속성이 포함됩니다:
- NacosConfigProperties: 현재 애플리케이션 네이커스의 기본 설정 정보
- RefreshHistory: 설정 새로고침 기록
- Sources: 현재 애플리케이션 설정 데이터 정보
액추에이터 웹 포트가 8081로 설정되어 있으므로, 다음 주소로 직접 접속할 수 있습니다: http://127.0.0.1:8081/actuator/nacos-config
서비스 응답 내용은 다음과 같습니다:
{
"NacosConfigProperties": {
"serverAddr": "127.0.0.1:8848",
"username": "",
"password": "",
"encode": null,
"group": "DEFAULT_GROUP",
"prefix": null,
"fileExtension": "properties",
"timeout": 3000,
"maxRetry": null,
"configLongPollTimeout": null,
"configRetryTime": null,
"enableRemoteSyncConfig": false,
"endpoint": null,
"namespace": null,
"accessKey": null,
"secretKey": null,
"contextPath": null,
"clusterName": null,
"name": null,
"sharedConfigs": null,
"extensionConfigs": null,
"refreshEnabled": true,
"sharedDataids": null,
"refreshableDataids": null,
"extConfig": null,
"configServiceProperties": {
"secretKey": "",
"namespace": "",
"username": "",
"enableRemoteSyncConfig": "false",
"configLongPollTimeout": "",
"configRetryTime": "",
"encode": "",
"serverAddr": "127.0.0.1:8848",
"maxRetry": "",
"clusterName": "",
"password": "",
"accessKey": "",
"endpoint": ""
}
},
"RefreshHistory": [],
"Sources": [
{
"lastSynced": "2020-09-14 11:11:37",
"dataId": "nacos-config-sample.properties"
},
{
"lastSynced": "2020-09-14 11:11:37",
"dataId": "nacos-config-sample"
}
]
}