앞서 Travis CI를 활용하여 배포 자동화 환경까지 구축했지만 배포하는 동안 애플리케이션이 종료되는 문제는 해결되지 않음 => 어떻게 해야 서비스 중단 없이 배포를 계속할 수 있을까?
🤍무중단 배포란?
- 서비스를 정지하지 않고 배포할 수 있는 방법
- AWS에서 블루 그린 무중단 배포 / 도커를 이용한 웹 서비스 무중단 배포
사용자는 서비스 주소로 접속 -> 엔진 엑스는 사용자의 요청을 받아 현재 연결된 스프링부트로 요청을 전달 -> 스프링부트2는 엔진엑스와 연결된 상태가 아니니 요청받지 못함.
배포하는 동안에도 서비스가 중단되지 않음!
🤍엔진엑스 설치와 스프링부트 연동하기
sudo yum install nginx //엔진엑스 설치
sudo service nginx start //엔진엑스 실행
리다이렉션 주소 추가
포트 번호가 8080이 아닌 80포트로 변경되므로 구글과 네이버 로그인에도 변경된 주소를 등록해야함.
추가 후 EC2의 도메인(8080 포트 제거 후)으로 접근하면 엔진엑스 웹 페이지를 볼 수 있음.
엔진엑스와 스프링부트 연동
- http://localhost:8080; -> 엔진엑스로 요청이 오면 8080으로 전달하겠다.
- proxy_set_header XXX -> 실제 요청 데이터를 header의 각 항목에 할당하겠다.
🤍무중단 배포 스크립트 만들기
ProfileController 생성, 간단한 API 코드 추가
🔍env.getActiveProfiles()
- 현재 실행 중인 ActiveProfile을 모두 가져옴.
- 여기에서는 real, oauth, real-db 3개 중 하나라도 있으면 그 값을 반환하도록 함.
테스트 코드 작성
- 스프링 환경이 필요하지 않으므로 @SpringBootTest 없이 작성
@Test
public void real_profile이_조회된다() {
//given
String expectedProfile = "real";
MockEnvironment env = new MockEnvironment();
env.addActiveProfile(expectedProfile);
env.addActiveProfile("oauth");
env.addActiveProfile("real-db");
ProfileController controller = new ProfileController(env);
//when
String profile = controller.profile();
//then
assertThat(profile).isEqualTo(expectedProfile);
}
@Test
public void real_profile이_없으면_첫_번째가_조회된다(){
//given
String expectedProfile = "oauth";
MockEnvironment env = new MockEnvironment();
env.addActiveProfile(expectedProfile);
env.addActiveProfile("real-db");
ProfileController controller = new ProfileController(env);
//when
String profile = controller.profile();
//then
assertThat(profile).isEqualTo(expectedProfile);
}
@Test
public void active_profile이_없으면_default가_조회된다(){
//given
String expectedProfile = "default";
MockEnvironment env = new MockEnvironment();
ProfileController controller = new ProfileController(env);
//when
String profile = controller.profile();
//then
assertThat(profile).isEqualTo(expectedProfile);
}
/profile 이 인증 없이 호출될 수 있도록 SecurityConfig 클래스 수정
테스트 코드 추가
현재 EC2 환경에서 실행되는 profile은 real 밖에 없으므로 profile 2개(real1, real2) 추가
//application-real1.properties
server.port=8082
spring.profiles.include=oauth, real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.session.store-type=jdbc
//application-real2.properties
server.port=8082
spring.profiles.include=oauth, real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.session.store-type=jdbc
엔진엑스 설정 수정
무중단 배포의 핵심은 엔진엑스 설정.
sudo vim /etc/nginx/conf.d/service-url.inc //배포 때마다 엔진엑스의 프록시 설정이 교체될 수 있도록 설정 추가
set $service_url http://127.0.0.1:8080;
sudo vim /etc/nginx/nginx.conf //엔진엑스가 사용할 수 있도록 설정
service_url 추가
저장 후 재시작
sudo service nginx restart
배포 스크립트 작성
step2와 중복되지 않게 디렉토리 생성
mkdir ~/app/step3/ && mkdir ~/app/step3/zip
앞으로 무중단 배포는 step3 디렉토리를 사용하도록 appspec.yml 수정
총 5가지 스크립트를 만들고 이 스크립트를 사용하도록 appspec.yml 내용 수정
- stop.sh : 기존 엔진엑스에 연결되어 있지 않으나 실행 중이던 스프링부트 종료
- start.sh: 배포할 신규 버전 스프링부트 프로젝트를 stop.sh로 종료한 'profile'로 실행
- health.sh: 'start.sh'로 실행시킨 프로젝트가 정상적으로 실행됐는지 체크
- switch.sh: 엔진엑스가 바라보는 스프링부트를 최신 버전으로 변경
- profile.sh: 앞선 4개 스크립트 파일에서 공용으로 사용할 'profile'과 포트 체크 로직
🤍무중단 배포 테스트
잦은 배포로 Jar 파일명이 겹치지 않도록 build.gradle 내용 수정
version '1.0.1-SNAPSHOT-'+new Date().format("yyyyMMddHHmmss")
위의 내용까지 수정 후 최종 코드를 깃허브로 푸시하고 배포를 진행했으나.....
빌드 실패😥 아직 확인 중이다
'💻 my code archive > 🏷️JAVA & Spring(Boot)' 카테고리의 다른 글
[스프링부트 블로그 만들기] Http 요청 방식, MIME 타입 (0) | 2022.03.15 |
---|---|
[스프링부트 블로그 만들기] STS 설치, 의존성, MySQL 세팅, 깃허브 연동, 프로젝트 실행하기 (0) | 2022.03.15 |
스프링부트 공부기록(16) - Travis CI 배포 자동화, S3, CodeDeploy 연동 (0) | 2022.03.08 |
스프링부트 공부기록(15) - EC2 배포하기, RDS 접근, EC2에서 구글,네이버 로그인하기 (0) | 2022.03.05 |
스프링부트 공부기록(14) - EC2 서버 배포 스크립트 작성, gradlew test 에러 원인, Junit5 맞게 코드 수정 해결 방법 (0) | 2022.03.05 |