구버전(Blue), 새로운 버젼 (Green)을 모두 올린 후 새로운 버젼으로 redirect한다.
Profile을 2가지 만든다.
Set1 : 8081 포트
Set2 : 8082 포트
현재 구동적인 프로그램의 Profile을 확인한다.
CURRENT_PROFILE=$(curl -s http://localhost/profile)
@GetMapping("/profile")
public String getProfile() {
return Arrays.stream(environment.getActiveProfiles())
.filter(profile -> profile.contains("set"))
.findFirst()
.orElse("");
}
현재 구동적인 Profile의 반대 Profile이 새로운 버전의 Profile이다.
if CURRENT_PROFILE == set1
IDLE_PROFILE = set2
IDLE_PORT = 8082;
else
IDLE_PROFILE = set1
IDLE_PORT = 8081;
새로운 버전의 Port에서 동작중인 작업을 kill한다.
echo "> $IDLE_PROFILE 에서 구동중인 애플리케이션 pid 확인"
IDLE_PID=$(ps -ef | grep java | grep $IDLE_PROFILE | awk '{print $2}')
echo "> pid : $IDLE_PID"
if [ -z $IDLE_PID ]
then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $IDLE_PID"
sudo kill -15 $IDLE_PID
echo "> 20초 뒤에 배포 시작"
sleep 20
fi
새로운 버전을 실행한다.
nohup java -jar -Dspring.profiles.active=$IDLE_PROFILE,prod $JAR_NAME 1> /dev/null 2>&1 &
Health Check하여 정상적으로 작동하는지 확인한다.
Spring Boot Acuator로 Health Check한다.
for retry_count in {1..10}
do
response=$(curl -s http://localhost:$IDLE_PORT/actuator/health)
up_count=$(echo $response | grep 'UP' | wc -l)
if [ $up_count -ge 1 ]
then
echo "> Health check 성공"
break
else
echo "> Health check의 응답을 알 수 없거나 혹은 status가 UP이 아닙니다."
echo "> Health check: ${response}"
fi
if [ $retry_count -eq 10 ]
then
echo "> Health check 실패. "
echo "> Nginx에 연결하지 않고 배포를 종료합니다."
exit 1
fi
echo "> Health check 연결 실패. 재시도..."
sleep 10
done
새로운 배포 버전으로 redirect하고 nginx 재시작
echo "set $service_url 127.0.0.1:${IDLE_PORT};" |sudo tee/etc/nginx/conf.d/service-url.inc
service_url : 80,443 port로 들어왔을 때 redirect 해주는 url
BlueGreen 배포를 찾아보니, A/B Testing과 비교하는 글이 많았다. (딱 봐도 엄청 다른데..? 🤔)
BlueGreen 배포와 A/B Testing은 2가지 프로그램을 띄운다는 것은 똑같다.
A/B Testing은 2가지 버전의 프로그램(A/B)으로 사용자의 반응을 확인하는 반면,
BlueGreen 배포는 하나의 프로그램만 사용자가 접근한다.
목적 자체도 BlueGreen 배포는 새로운 버전으로 release하는 것이다.