-
Spring-Cloud-Config서버Back-end/Spring 2021. 12. 17. 22:42반응형
문제
무중단 배포를 하려고 하면 로드 밸런서 하나에 서버가 최소 2개 이상은 필요로합니다.
그렇다면 저희는 서버를 4개 운영하고 있습니다. 하나하나 설정파일을 Git Pull해서 서버중단 후 배포해야할까요?
물론 이러한 불편함은 감수할 수 있지만 큰 문제점이 있습니다.
바로 코드와 설정 파일이 서로 의존성을 가지고 있어 설정파일 내용을 바꾸려고 하면 무조건 서버를 끄고 다시
실행해야하는 불편함이 있습니다. 아래 대표적인 예시를 들겠습니다.
@Value("${username}") pritvate String username;
위의 @Value어노테이션은 환경설정 파일의 값을 정해놓고 읽어오는 변수입니다.
만약 서버의 admin권한을 가지려면 위의 필드에 값이 꼭 들어가야하는 경우 이름을 계속 필요할 때 바꿔줘야합니다.
그 때 마다 계속 서버를 켜고 끄고를 반복하다보면 서비스에 장애가 생기기 마련입니다.
이러한 문제점들로 Spring-Cloud-Config서버를 이용해 서버를 끄지 않고 설정을 바꿀 수 있게 전환하였습니다.
적용
일단 현재 서버의 여유가 없어 Visitor-Dev서버의 포트를 2개로 나눠 관리하도록 했습니다.
아래의 그림과 같이 구성하였습니다.
1. Spring-Cloud-Server
GitHub과 Client들을 연동시켜주는 역할을 합니다.
plugins { id 'org.springframework.boot' version '2.6.1' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' repositories { mavenCentral() } ext { set('springCloudVersion', "2021.0.0") } dependencies { implementation 'org.springframework.cloud:spring-cloud-config-server' testImplementation 'org.springframework.boot:spring-boot-starter-test' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } } test { useJUnitPlatform() }
현재 Spring-Cloud같은 경우는 SpringBoot와의 호환성 문제로 아래의 링크 테이블을 참조하여 버전들을 설정했습니다.
링크 : https://spring.io/projects/spring-cloud
Spring Cloud
Spring Cloud is an umbrella project consisting of independent projects with, in principle, different release cadences. To manage the portfolio a BOM (Bill of Materials) is published with a curated set of dependencies on the individual project. Go here to r
spring.io
<ApplicationServer.java>
@SpringBootApplication @EnableConfigServer public class SpringCloudServerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudServerApplication.class, args); } }
<application.yml>
server: port: 8888 spring: cloud: config: server: git: uri: ${BITBUCKET_URL} username: ${BITBUCKET_ID} password: ${BITBUCKET_PW}
그리고 원래 Public Repository같은 경우는 username과 password가 필요없습니다.
저희는 Private Repository로 관리하고 있기 때문에 꼭 넣어주셔야 합니다. SSH-Key를 사용하는 방법도 가능합니다.
아래의 그림은 최종 Bitbucket Repository에 올라와있는 파일들입니다.
2. Spring Config Client
현재 클라이언트 같은 경우는 동일 서버내에 하나 외부 서버 3개로 이루어져 있습니다.
그래서 EC2의 인바운드 규칙부터 수정을 해줘야합니다. 여기서 동일 서버내에서는 별도의 인증없이 접근 가능합니다.
각 서버로부터오는 포트 8888로 오는 요청만을 열어두었습니다.
<bootstrap.yml>
spring: profiles: active: ${ENV_START} #Github에 올라가있는 버전의 이름 application: name: visitor #Github에 올라가있는 App의 이름 config: import: ${ENV_CONFIG_URL} # <actuator관련> management: endpoints: web: exposure: include: refresh
<build.gradle>
buildscript { ext { queryDslVersion = "5.0.0" } } plugins { id 'org.springframework.boot' version '2.6.1' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.ftseoul' version = '1.1.0' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-websocket' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation platform('software.amazon.awssdk:bom:2.16.95') implementation 'software.amazon.awssdk:sns' compileOnly 'org.springframework.cloud:spring-cloud-aws-messaging:2.2.1.RELEASE' compileOnly 'org.springframework.cloud:spring-cloud-aws-autoconfigure:2.2.1.RELEASE' compileOnly 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' runtimeOnly 'mysql:mysql-connector-java' implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16' implementation group: 'commons-io', name: 'commons-io', version: '2.4' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" testImplementation 'org.springframework.boot:spring-boot-starter-test' testCompileOnly 'org.springframework.boot:spring-boot-starter-test' implementation group: 'net.gpedro.integrations.slack', name: 'slack-webhook', version: '1.4.0' //spring-cloud-config implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.cloud:spring-cloud-starter-config:3.1.0' implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.0' // QueryDSL implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" annotationProcessor( "javax.persistence:javax.persistence-api", "javax.annotation:javax.annotation-api", "com.querydsl:querydsl-apt:${queryDslVersion}:jpa") } // QueryDSL sourceSets { main { java { srcDirs = ["$projectDir/src/main/java", "$projectDir/build/generated"] } } } test { useJUnitPlatform() }
위의 설정과 다르시다는 것을 느끼셨을겁니다. 현재 queryDsl버전과 SpringBoot버전의 호환성, Spring-Cloud버전과
Spring-Boot의 호환성 문제로 인해 queryDsl(4.4.0->5.0.0), SpringBoot(2.4.4->2.6.1)로 버전업을 진행하였습니다.
그리고 starter-actuator같은 경우는 스프링 부트 어플리케이션에서 제공하는 모든 정보들을 모니터링하기 쉽게해주는
기능입니다. 이것은 @RefreshScope어노테이션과 함께 yml파일이 업데이트 될 경우 무조건 업데이트 되는게 아니라
post방식의 {baseUrl}/actuator/refresh 명령을 주어야만 업데이트가 됩니다. 안전장치로써 사용합니다.
바로 업데이트 할 수 있는 방법은 Spring Cloud Bus를 사용하시면 한 번에 연관된 모든 서버들이 업데이트됩니다.
실습
이렇게 설정을 마치고 난 후 실습을 해보겠습니다.
현재의 version은 ‘1.1.0’입니다. 위의 그림과 같습니다. version을 서버에서 출력한 것입니다.
다음으로 BitBucket의 환경설정 파일을 ‘1.2.0’ → ‘9.9.9’으로 업데이트 하겠습니다. 서버를 끄지 않고 말이죠.
아직 바뀌지 않았습니다. actuator에 명령을 줘야하기 때문이죠.
그럼 curl -X POST '/actuator/refresh'을 보내고 출력해보겠습니다.
version이 9.9.9로 변경되었습니다. 서버를 끄지 않고 말이죠.
이렇게 spring-cloud-config에 대해서 사용해봤습니다. 조금 까다로운 부분이 많았지만 장점에 대해서 말씀드리겠습니다.
첫 번째로 서버를 끄지 않아도 된다는 점입니다. 즉 쉽게 테스트를 해볼 수 있다는게 장점입니다.
서버가 무거워 질수록 끄고 켜는데 많은 시간이 걸립니다. 이러한 문제를 해결해줘서 좋았습니다.
두 번째로 환경파일 관리가 용이하다는 점입니다. 작업하는 경우에 환경변수이름을 잘못넣은 경우를 예로 들겠습니다.
이 때는 develop → 테스트 → main → 테스트 → 배포하는 과정을 거쳐야하기에 상당히 까다로웠습니다.
그러나 config를 모아놓으면 위의 프로세스가 repository update → curl -X POST '{baseUrl}/actuator/refresh’ 과정으로 매우
줄어들게 됩니다.
반응형'Back-end > Spring' 카테고리의 다른 글
Spring(6) - Mock, Mockito (0) 2021.08.25 Spring(5) - @Transactional (0) 2021.08.18 Spring(4) - 의존 관계 주입, DI(Dependency Injection) (0) 2021.07.11 Spring(3) - Bean등록하는 방법 (0) 2021.06.24 Spring(2) - Junit Test과 Spring Test (0) 2021.06.24