반응형

Spring Cloud Config Server

Config Server?

  • 분산 시스템에서 설정 파일을 외부로 분리해서 중앙에서 관리하는 기능을 제공한다
  • git을 활용해 설정 파일을 관리한다
  • Config Server에서 설정값을 관리하고, Config Client들에게 설정 정보를 제공한다
  • 서비스별 개발, 테스트, 운영 환경 설정을 한 곳에서 관리할 수 있다
  • 운영 중 설정 변경이 필요하더라도 서버 빌드나 배포를 할 필요 없이 변경 가능하다

설정 관리를 위한 git 레파지토리 생성

  • repository name
    • spring-msa-config-properties
  • ssh key 생성 후 public key를 git repository의 deploy key로 등록
  • 아래처럼 옵션을 주어 생성하지 않으면 config server 띄울 때 인증 오류가 발생하므로 주의 필요
ssh-keygen -m PEM -t rsa -b 4096

설정 정보 추가 후 푸시

  • 설정 정보 파일명은 {service-name}-{profile}.yml 형식으로 작성해야 한다
  • ~/spring-msa-web.yml
    server:
      port: 8181
    
  • ~/spring-msa-web-dev.yml
    app:
      name: spring-msa-web-dev
      desc: spring-msa-web-dev
    
  • ~/spring-msa-web-real.yml
    app:
      name: spring-msa-web-real
      desc: spring-msa-web-real
    

Config Server 프로젝트 생성

  • project name
    • spring-msa-config
  • pom.xml
    • spring-boot와 spring-cloud-config-server가 호환이 잘 안되는 버전으로 사용하면 정상 작동하지 않을 수 있음
    • spring-boot:2.3.7.RELEASE
    • spring-cloud-config-server:2.2.6.RELEASE
    • spring-cloud:Hoxton.SR9
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.7.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>spring-msa-config</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-msa-config</name>
        <description>Demo project for Spring Boot</description>
      
        <properties>
            <java.version>11</java.version>
            <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
        </properties>
      
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
      
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
            </dependency>
        </dependencies>
      
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
      </project>
      
  • @EnableConfigServer 어노테이션 설정
    @EnableConfigServer
    @SpringBootApplication
    public class SpringMsaConfigApplication {
        public static void main(String[] args) {
            SpringApplication.run(SpringMsaConfigApplication.class, args);
        }
    }
    
  • application.yml 설정
    server:
      port: 8888
    
    spring:
      profiles:
        active: local
      application:
        name: spring-msa-config
    
      cloud:
        config:
          server:
            git:
              uri: git@github.com:your-account/spring-msa-config-properties.git
              ignore-local-ssh-settings: true
              # search-paths:
                # - spring-msa-web # spring-msa-config-properties에서 디렉토리로 나눠 관리할 경우 해당 디렉토리 명시
              private-key: |
                -----BEGIN RSA PRIVATE KEY-----           
                MIIJKAIBAAKCAgEAvI/mHa/cXixuSx/KT/o91M9FQqwf3bV6NIjcO7ZuF+pdZmNa
                ....
                XuGLOTTGUAvOOXKXzriFGStmVNEzxtGo1dfSUpQKmbzBntG+5NfrY35bV/0=
                -----END RSA PRIVATE KEY----- ```
    

실행 후 확인

  • 요청 URL은 /{service-name}/{profile}/{branch} 형식을 따른다
### 설정 정보 조회
GET http://localhost:8888/spring-msa-web/dev/master
{
    "name": "spring-msa-web",
    "profiles": [
        "dev"
    ],
    "label": "master",
    "version": "ca11efe97eadd2aa07c54e27eb7901d5383166e1",
    "state": null,
    "propertySources": [
        {
            "name": "git@github.com:sanggeun-choi/spring-msa-config-properties.git/spring-msa-web/spring-msa-web-dev.yml",
            "source": {
                "app.name": "spring-msa-web-dev",
                "app.desc": "spring-msa-web-dev"
            }
        },
        {
            "name": "git@github.com:sanggeun-choi/spring-msa-config-properties.git/spring-msa-web/spring-msa-web.yml",
            "source": {
                "server.port": 8181
            }
        }
    ]
}

참고

Spring Cloud Config Client

Config Client?

  • Config Server에서 원격으로 관리하는 설정 정보를 받아와 사용하는 주체를 말한다

Config Client 프로젝트 설정

  • project name
    • spring-msa-web
  • pom.xml
    • spring-boot:2.3.7.RELEASE
    • spring-cloud-starter-config:2.2.6.RELEASE
    • spring-cloud:Hoxton.SR9
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.7.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>spring-msa-web</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-msa-web</name>
        <description>Demo project for Spring Boot</description>
      
        <properties>
            <java.version>11</java.version>
            <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
        </properties>
      
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
      
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>
      
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
      </project>
      
  • ~/src/main/resource/bootstrap.yml
    • bootstrap.yml은 application.yml보다 먼저 로드된다
      spring:
        application:
          name: spring-msa-web
      
        profiles:
          active: dev
      
        cloud:
          config:
          uri: http://localhost:8888
          label: master # branch (default: master)
      
      management:
        endpoints:
          web:
          exposure:
              include: refresh
      

설정 조회 컨트롤러 작성

@RestController
@RefreshScope // refresh 요청 받았을 때 설정 갱신이 되는 대상을 명시
public class TestController {
    @Value("${app.name}")
    private String appName;

    @Value("${app.desc}")
    private String appDesc;

    @GetMapping("/api/properties")
    public Map<String, String> getProperties() {
        return Map.of(
            "appName", appName,
            "appDesc", appDesc
        );
    }
}

실행 후 확인

서버 실행하여 spring-msa-config-properties에 설정한 값(port=8181)으로 잘 뜨는지 확인
Tomcat started on port(s): 8181 (http) with context path ''
설정 정보 조회
### config client에 설정 조회 요청
GET http://localhost:8181/api/properties
{
    "appName": "spring-msa-web-dev",
    "appDesc": "spring-msa-web-dev"
}

설정 변경하기

spring-msa-config-properties 수정 후 푸시 (spring-msa-web-dev.yml)
app:
  name: spring-msa-web-dev2
  desc: spring-msa-web-dev2
config client에 설정 변경 반영 요청 (설정 변경시 각 client에 요청해주어야함)
### config client에 설정 변경 반영 요청
POST http://localhost:8181/actuator/refresh
[
    "config.client.version",
    "app.name",
    "app.desc"
]
설정 정보 재조회
### config client에 설정 조회 요청
GET http://localhost:8181/api/properties
{
    "appName": "spring-msa-web-dev2",
    "appDesc": "spring-msa-web-dev2"
}

참고

Spring Cloud Bus

Spring Cloud Bus?

  • 분산 시스템에 존재하는 노드들을 경량 메시지 브로커(RabbitMQ, Kafka, Redis 등)와 연결하는 역할을 수행한다
  • Config Server와 Config Client가 모두 메시지 브로커에 연결되어 메시지를 주고받을 수 있다
  • 설정 변경시 Config Server에 변경 반영 요청을 하면 모든 Config Client에 브로드 캐스트하여 반영할 수 있다

RabbitMQ 서버 실행(Docker 활용)

  • IP : 192.168.56.12
version: "3.3"
services:
  rabbitmq:
    container_name: rabbitmq
    image: rabbitmq:3-management
    environment:
      TZ: "Asia/Seoul"
      RABBITMQ_DEFAULT_USER: "guest"
      RABBITMQ_DEFAULT_PASS: "guest"
      RABBITMQ_DEFAULT_VHOST: "test"
    ports:
      - "5672:5672"
      - "15672:15672"

Config Server 설정

의존성 추가
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
application.yml에 설정 추가
spring:
  rabbitmq:
    host: 192.168.56.12
    port: 5672
    username: guest
    password: guest
    virtual-host: test

management:
  endpoints:
    web:
      exposure:
        include: bus-refresh

Config Client 설정

의존성 추가
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
원격 저장소 설정 파일에 아래 내용 추가 (spring-msa-web-dev.yml, spring-msa-web-real.yml)
spring:
  rabbitmq:
    host: 192.168.56.12
    port: 5672
    username: guest
    password: guest
    virtual-host: test

설정 변경 테스트

Config Client에 설정값 조회 요청
### config client에 설정 조회 요청
GET http://localhost:8181/api/properties
{
    "appName": "spring-msa-web-dev",
    "appDesc": "spring-msa-web-dev"
}
원격 저장소 설정 파일 내용 수정
app:
  name: spring-msa-web-dev222
  desc: spring-msa-web-dev222
Config Server에 설정값 반영 요청
### config server에 설정 변경 broadcast 요청
POST http://localhost:8888/actuator/bus-refresh
Config Client 설정값 재조회 요청
### config client에 설정 조회 요청
GET http://localhost:8181/api/properties
{
    "appName": "spring-msa-web-dev222",
    "appDesc": "spring-msa-web-dev222"
}

참고

반응형

'Development > Spring' 카테고리의 다른 글

[Spring] Spring Cloud Hystrix  (0) 2020.12.27
[Spring] Spring Cloud Eureka  (0) 2020.12.27
[Spring] SQL Mapper (with MyBatis)  (0) 2020.12.27
[Spring] ORM (with JPA, Hibernate)  (0) 2020.12.27
[Spring] WebSocket  (0) 2020.12.27

+ Recent posts