본글에서는 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에 실시간으로 반영시키는 방법을 구현해보겠습니다.
'spring' 카테고리의 다른 글
spring Mock Test (0) | 2024.03.12 |
---|---|
spring EventListener에서 @Async 비동기 적용 (0) | 2023.07.31 |
spring event pub/sub 구현 (0) | 2023.07.22 |
spring application.yml파일 설정값 적용 (0) | 2023.07.21 |
spring jwt 인증인가 인터셉터 만들기 (0) | 2023.07.08 |
spring 쓰레드로컬(ThreadLocal) (0) | 2023.07.08 |
spring jwt 토큰 발급하는 restapi 만들기 -2 (0) | 2023.07.05 |
spring security로 ID/PASSWORD 로그인 구현하기 (2) | 2023.06.28 |
댓글