스프링부트 공부기록(17) - 무중단 배포 만들기
my code archive
article thumbnail
반응형

앞서 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")

 

위의 내용까지 수정 후 최종 코드를 깃허브로 푸시하고 배포를 진행했으나.....

빌드 실패😥 아직 확인 중이다

반응형
profile

my code archive

@얼레벌레 개발자👩‍💻

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

반응형