Skip to content

소중단 배포

Soap edited this page May 29, 2024 · 2 revisions

자동 배포시 서버의 다운타임을 줄이기 위해 Nginx 가 두 Spring boot 로 트래픽을 로드 밸런싱 하도록 설정 각각 어플리케이션은 github action 에서 빌드 후 docker hub에 push -> deploy.sh 실행해 배포

  • docker-compos.yml
version: '3.8'

services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl

  app1:
    image: miensoap/issue_tracker:latest
    environment:
      - SPRING_PROFILES_ACTIVE=dev
    ports:
      - "8081:8080"

  app2:
    image: miensoap/issue_tracker:latest
    environment:
      - SPRING_PROFILES_ACTIVE=dev
    ports:
      - "8082:8080"

nginx.conf

events {}

http {
    upstream backend {
        server app1:8080;
        server app2:8080;
    }

    server {
        listen 80;
        server_name issuetracker01.site www.issuetracker01.com;
        return 307 https://$host$request_uri;  # HTTP 요청을 HTTPS로 리디렉션
    }

    server {
        listen 443 ssl;
        server_name issuetracker01.com www.issuetracker01.com;

        ssl_certificate /etc/nginx/ssl/issuetracker01.crt;
        ssl_certificate_key /etc/nginx/ssl/issuetracker01.key;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Authorization $http_authorization;
            proxy_pass_header Authorization;
        }
    }
}
  • deploy.sh
#!/bin/bash

# Pull the latest version of the application
docker-compose pull app1 app2 2>/dev/null


# Gracefully stop the old instance of app1
docker-compose stop app1
docker-compose rm -f app1

# Start a new instance of the application
docker-compose up -d app1

# Wait for app1 to be ready
until $(curl --output /dev/null --silent --head --fail http://localhost:8081/ac/health); do
    echo "Waiting for app1 to be ready..."
    sleep 5
done

# Gracefully stop the old instance of app2
docker-compose stop app2
docker-compose rm -f app2

# Start the new instance of app2
docker-compose up -d app2

# Optionally, clean up unused images
docker system prune -f
  1. app1컨테이너를 먼저 중지시킨 뒤, 새 이미지로 다시 실행
  2. app1 컨테이너 내의 spring boot 가 실행되어 서버가 정상 동작 하는지 curl 명령어로 5초마다 요청해 확인
    • 이때 spring actuatorhealth 사용
  3. app1 배포가 끝나면 app2 컨테이너를 중단 후 새 버전 배포

테스트 결과

스크린샷 2024-05-26 130423

블로그 참고하여 0.1초마다 반복 요청으로 2분간 테스트 -> 약 0.04% 요청 실패

  • request-auto.sh
#!/bin/bash

URL="https://issuetracker01.site/"  # 원하는 URL로 변경
TOTAL_REQUESTS=0
SUCCESS_COUNT=0
FAILURE_COUNT=0
REQUEST_INTERVAL=0.1
DURATION=120 # 실행 시간
START_TIME=$(date +%s) # 스크립트 시작 시간

# 반복 요청
while true; do
    CURRENT_TIME=$(date +%s)
    ELAPSED_TIME=$((CURRENT_TIME - START_TIME))

    if [ $ELAPSED_TIME -ge $DURATION ]; then
        break     # 실행 시간이 DURATION을 초과하면 종료
    fi

    # URL에 GET 요청을 보내고 결과를 저장 (성공 또는 실패)
    RESPONSE=$(curl -k -s -o /dev/null -w "%{http_code}" "$URL")

    # 결과에 따라 성공 및 실패 횟수 증가
    if [ "$RESPONSE" = "200" ]; then
        SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
    else
        FAILURE_COUNT=$((FAILURE_COUNT + 1))
    fi

    TOTAL_REQUESTS=$((TOTAL_REQUESTS + 1))

    sleep $REQUEST_INTERVAL # 간격 유지
done

# 결과 출력
echo "Total Requests: $TOTAL_REQUESTS"
echo "Total Requests: $TOTAL_REQUESTS"
echo "Success Count: $SUCCESS_COUNT"
echo "Failure Count: $FAILURE_COUNT"    

소중단 배포 성공!

Clone this wiki locally