본문 바로가기
spring

spring cloud config로 yml파일 배포없이 변경해보기

by 토망이 2023. 7. 23.

본글에서는 spring cloud config를 통해 yml파일을 배포없이 변경사항을 반영해보는 것을 구현하려 합니다. 보통 서비스에서 application.yml하나만 적용하지 않고, profile 관리를통해 

개발서버: application.yml + application-dev.yml

운영서버 : application.yml + application.prd.yml

이런식으로, 공통사항은 application.yml에 넣고, DB정보와 같이 개발/운영이 별도로 관리되어야하는 항목은 각 dev, prd 프로파일에 추가하여 사용하였습니다. 그런데 yml파일 변경시에 서비스 중단 없이 배포를 할수 있는데, 마이크로서비스아키텍쳐에서 중요한 개념으로 보여 spring cloud config를 통해 적용해보고자 합니다.

 

- config.repo

: 먼저 yml파일이 저장된 git repository가 필요합니다. 해당 레파지토리에서 서비스명-(profile).yml 의 명칭으로 각각 서로다른 yml파일을 생성후 저장해놓습니다.(https://github.com/dnl1029/cloud-config-repo/blob/master/serviceA-dev.yml)

 

그 후 config-server 서비스를 만듭니다. 의존성이 조금 복잡하여 수동으로 추가하기 힘드므로, start.spring.io에서 참고하도록 합시다.

 - config-server의 application.yml

server:
  port: 8888
spring:
  application:
    name: configserver
  cloud:
    config:
      server:
        git:
          uri: https://github.com/dnl1029/cloud-config-repo
          default-label: master

 

- config-server의 메인메서드에 @EnableConfigServer 추가

@SpringBootApplication
@EnableConfigServer
public class CloudserverApplication {

	public static void main(String[] args) {
		SpringApplication.run(CloudserverApplication.class, args);
	}

}

 

그 후, 로컬에서 서버를 띄우고, postman이나 혹은 그냥 url에 다음과 같이 입력하면, 바로 response를 받을수있습니다. 응답이 오지 않는다면, config-repo쪽이나 server쪽에 설정이 잘못된것입니다. (http://localhost:8888/serviceA/dev)

 

위의 http://localhost:8888/serviceA/dev 에서 response값을 cloud config client단에서 받아서 사용하는 구조입니다.

이제 별도로 client 서비스를만들어보겠습니다. 마찬가지로 start.spring.io에서 의존성을 참고합니다.

 

- client의 application.yml

: config.repo에 있는 application 명(serviceA)와 반드시 동일하게 client에서 application 명칭을 지정해줘야 합니다.

config.repo 주소 : (https://github.com/dnl1029/cloud-config-repo/blob/master/serviceA-dev.yml)

또한 config.repo에 없는 y라는 값을 의도적으로 추가했습니다. 

spring:
  application:
    name: serviceA
  profiles:
    active: dev
  config:
    import: optional:configserver:http://localhost:8888

configtest:
  y: 10

 

- ClientConfig

@Setter
@Getter
@ConfigurationProperties("configtest")
@RefreshScope
@ToString
public class ClientConfig {

    private String x;
    private String profile;
    private String y;

}

 

- Client main

@SpringBootApplication
@EnableConfigurationProperties(ClientConfig.class)
public class CloudclientApplication {

	public static void main(String[] args) {
		SpringApplication.run(CloudclientApplication.class, args);
	}

}

 

- Client Controller

: ClientConfig에 설정된 값들을 확인하는 테스트용 api를 작성합니다. config.repo 주소에는 x라는 값과 profile이라는 값밖에 없지만, y라는 값도 불러옵니다.

application.yml(config-client단) + application-dev.yml(config-repo) 값을 합쳐서 적용하게 됩니다. 

만약 아래와 같이 동일하게 yml파일이 있다 했을때, 우선순위는 4>3>2>1이 됩니다. 모두 중복인 값이 있을시에 4의 값을 적용합니다. 헷갈리지 않기 위하여 client단에는 application.yml과 application-dev.yml을 모두 삭제하는게 좋을것같습니다. 

1) client의 application yml

2) gitrepo의 application.yml

3) client의 application-dev.yml

4) gitrepo의 application-dev.yml

@RestController
@Slf4j
@RequiredArgsConstructor
@RequestMapping("api")
public class ClientController {

    private final ClientConfig clientConfig;

    @GetMapping("/config")
    @CacheEvict
    public ResponseEntity<String> config() {
        log.info("clientconfig : {}",clientConfig);
        return ResponseEntity.ok(clientConfig.toString());
    }

}

 

- swagger에서 테스트를 위해 아래 의존성을 추가해줍니다.

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.0.2</version>
</dependency>

 

- swagger 테스트(http://localhost:8080/swagger-ui/index.html)

 

- 결과 : 

 

config.repo에 있는 파일을 수정하면 변경사항이 바로 반영될까요? 테스트를 위해 x라는 값을 바꿔봅시다.

[AS-IS]

 

[TO-BE]

 

- config-server에서 바로 조회하니, 아래와 같이 실시간으로 x 값이 5->7로 변경됩니다.(http://localhost:8888/serviceA/dev)

- client swagger api 재실행

: x값이 그대로 5로 남아있습니다. 설정정보를 읽고 로컬에 캐싱하는 것으로 보입니다. 아래 현상을 해결하기위해서는 서버를 내렸다 올리면 되지만, 그러면 spring cloud config를 쓰는 의미가없겠죠? 다음글에서는 config-repo의 변경사항을 client에 실시간으로 반영시키는 방법을 구현해보겠습니다.

댓글