Skip to content

Commit

Permalink
[Feat]NGINX server set
Browse files Browse the repository at this point in the history
  • Loading branch information
Han-Jeong committed Jan 9, 2024
1 parent d46503f commit e6d9324
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 8 deletions.
14 changes: 11 additions & 3 deletions appspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/app/step2/zip/
destination: /home/ec2-user/app/step3/zip/
overwrite: yes

permissions:
Expand All @@ -11,8 +11,16 @@ permissions:
owner: ec2-user
group: ec2-user

hooks:
hooks: # CodeDeploy 배포 단계에서 실행할 명령어
AfterInstall:
- location: stop.sh # 엔진엑스와 연결되어 있지 않은 스프링 부트를 종료
timeout: 60 # 스크립트 실행 60초 이상 수행되면 실패 (무한 대기할 수는 없으니 설정)
runas: ec2-user
ApplicationStart:
- location: deploy.sh
- location: start.sh # 엔진엑스와 연결되어 있지 않은 Port로 새 버전의 스프링 부트를 시작
timeout: 60
runas: ec2-user
ValidateService:
- location: health.sh # 새 스프링 부트가 정상적으로 실행됐는지 확인
timeout: 60
runas: ec2-user
43 changes: 43 additions & 0 deletions scripts/health.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

# start.sh로 실행시킨 프로젝트가 정상적으로 실행됐는지 체크
ABSPATH=$(readlink -f $0)
ABSDIR=$(dirname $ABSPATH)
source ${ABSDIR}/profile.sh
source ${ABSDIR}/switch.sh

IDLE_PORT=$(find_idle_port)

echo ">>> Health Check Start!"
echo ">>> IDLE_PORT: $IDLE_PORT"
echo ">>> curl -s http://localhost:$IDLE_PORT/profile"
sleep 10

# for 문 10번 돌기
for RETRY_COUNT in {1..10}
do
# 현재 문제 없이 잘 실행되고 있는 요청을 보내봅니다.
RESPONSE=$(curl -s http://localhost:${IDLE_PORT}/profile)
# 해당 결과의 줄 수를 숫자로 리턴합니다.
UP_COUNT=$(echo ${RESPONSE} | grep 'set' | wc -l)

if [ ${UP_COUNT} -ge 1 ]
then # $up_count >= 1 ("set" 문자열이 있는지 검증)
echo ">>> Health check 성공"
switch_proxy # switch.sh 실행
break
else
echo ">>> Health check의 응답을 알 수 없거나 혹은 실행 상태가 아닙니다."
echo ">>> Health check: ${RESPONSE}"
fi

if [ ${RETRY_COUNT} -eq 10 ]
then
echo ">>> Health check 실패. "
echo ">>> 엔진엑스에 연결하지 않고 배포를 종료합니다."
exit 1
fi

echo ">>> Health check 연결 실패. 재시도..."
sleep 10
done
39 changes: 39 additions & 0 deletions scripts/profile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash

# 쉬고 있는 profile 찾기
# set1이 사용중이면 set2가 쉬고 있으며, 반대편 set1이 쉬고 있다.
function find_idle_profile()
{
RESPONSE_CODE=$(sudo curl -s -o /dev/null -w "%{http_code}" http://localhost/profile)

if [ ${RESPONSE_CODE} -ge 400 ] # 400 보다 크면 (즉, 40x/50x 에러 모두 포함)
then
CURRENT_PROFILE=real2
else
CURRENT_PROFILE=$(sudo curl -s http://localhost/profile)
fi

if [ ${CURRENT_PROFILE} == real1 ]
then
IDLE_PROFILE=real2 # Nginx와 연결되지 않은 profile
else
IDLE_PROFILE=real1
fi

# bash script는 return 기능이 없기 떄문에,
# echo를 통해서 출력하면 이 값을 클라이언트가 사용할 수 있습니다.
echo "${IDLE_PROFILE}"
}

# 쉬고 있는 profile의 port 찾기
function find_idle_port()
{
IDLE_PROFILE=$(find_idle_profile)

if [ ${IDLE_PROFILE} == real1 ]
then
echo "8081" # 여기도 마찬가지로 return 기능의 느낌
else
echo "8082"
fi
}
32 changes: 32 additions & 0 deletions scripts/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash

# 배포할 신규 버전 프로젝트를 stop.sh로 종료한 profile로 실행
ABSPATH=$(readlink -f $0)
ABSDIR=$(dirname $ABSPATH)
source ${ABSDIR}/profile.sh # 해당 코드로 profile.sh 내의 함수 사용

REPOSITORY=/home/ec2-user/app/step3

echo ">>> Build 파일 복사"
echo ">>> cp $REPOSITORY/zip/build/libs/*.jar $REPOSITORY/"

cp $REPOSITORY/zip/build/libs/*.jar $REPOSITORY/

echo ">>> 새 어플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1) # jar 이름 꺼내오기

echo ">>> JAR Name: $JAR_NAME"
echo ">>> $JAR_NAME 에 실행 권한 추가"
chmod +x $JAR_NAME

echo ">>> $JAR_NAME 실행"
IDLE_PROFILE=$(find_idle_profile)

# 위에서 보았던 것처럼 $IDLE_PROFILE에는 set1 or set2가 반환되는데
# 반환되는 properties를 실행한다는 뜻.
echo ">>> $JAR_NAME 를 profile=$IDLE_PROFILE 로 실행합니다."

nohup java -jar \
-Dspring.config.location=classpath:/application.yml,/home/ec2-user/app/application-security.yml,/home/ec2-user/app/application-s3.yml,/home/ec2-user/app/application-real-db.yml,classpath:/application-real.yml, classpath:/application-real1.yml, classpath:/application-real2.yml \
-Dspring.profiles.active=$IDLE_PROFILE \
$JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
21 changes: 21 additions & 0 deletions scripts/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash

# 기존 Eginx엔스에 연결되어 있지 않지만, 실행 중이던 스프링 부트 종료
ABSPATH=$(readlink -f $0)
ABSDIR=$(dirname $ABSPATH) # 현재 stop.sh가 속해있는 경로
source ${ABSDIR}/profile.sh # 해당 코드로 profile.sh 내의 함수 사용

IDLE_PORT=$(find_idle_port)

echo ">>> $IDLE_PORT 에서 구동중인 애플리케이션 PID 확인"
IDLE_PID=$(sudo lsof -ti tcp:${IDLE_PORT})

if [ -z ${IDLE_PID} ]
then
echo ">>> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
# # Nginx에 연결되어 있지는 않지만 현재 실행 중인 jar 를 Kill 합니다.
echo ">>> kill -15 $IDLE_PID"
kill -15 ${IDLE_PID}
sleep 5
fi
17 changes: 17 additions & 0 deletions scripts/switch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

# Ngnix가 바라보는 스프링 부트를 최신 버전으로 변경
ABSPATH=$(readlink -f $0)
ABSDIR=$(dirname $ABSPATH)
source ${ABSDIR}/profile.sh

function switch_proxy() {
IDLE_PORT=$(find_idle_port)

echo ">>> 전환할 Port: $IDLE_PORT"
echo ">>> Port 전환"
# 아래 줄은 echo를 통해서 나온 결과를 | 파이프라인을 통해서 service-url.inc에 덮어쓸 수 있습니다.
echo "set \$service_url http://127.0.0.1:${IDLE_PORT};" | sudo tee /etc/nginx/conf.d/service-url.inc
echo ">>> Reload Nginx"
sudo service nginx reload # Nginx reload를 합니다.
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti
.requestMatchers(HttpMethod.POST, "/api/tokens").permitAll()
// SWAGGER
.requestMatchers("/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**").permitAll()
//profile
.requestMatchers("/api/profiles").permitAll()
// ELSE
//정적 페이지 허가
.requestMatchers("/", "/css/**", "/*.ico", "/error", "/images/**").permitAll() // 임시로 모든 API 허용
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.example.waggle.web.controller;

import com.example.waggle.global.payload.ApiResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
@RequiredArgsConstructor
public class ProfileController {

private final Environment env;

@GetMapping("/profile")
public ApiResponseDto<String> getProfile() {
List<String> profile = Arrays.asList(env.getActiveProfiles());
List<String> realProfiles = Arrays.asList("real1", "real2");
String defaultProfile = profile.isEmpty() ? "default" : profile.get(0);

String result = profile.stream()
.filter(realProfiles::contains)
.findAny()
.orElse(defaultProfile);

return ApiResponseDto.onSuccess(result);
}
}
10 changes: 5 additions & 5 deletions src/main/resources/application-real.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
spring:
profiles:
include:
- security
- real-db
- s3
# profiles:
# include:
# - security
# - real-db
# - s3
jpa:
properties:
hibernate:
Expand Down
10 changes: 10 additions & 0 deletions src/main/resources/application-real1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
server:
port: 8081

spring:
profiles:
include:
- security
- real-db
- s3
- real
10 changes: 10 additions & 0 deletions src/main/resources/application-real2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
server:
port: 8082

spring:
profiles:
include:
- security
- real-db
- s3
- real

0 comments on commit e6d9324

Please sign in to comment.