SpringBootプロジェクトNginx無停止配置スクリプト


の原因となる


単一のawsec 2インスタンスでは、無停止の導入が必要になる状況が到来しました.実行エラー時に完了したデプロイメントスクリプトを共有します.プロジェクトはspringboot+gradleベースのプロジェクトで、nginxサーバを使用しています.アプリケーション側でポート構成情報や健康診断に関連するコントローラを作成し、これらの情報に基づいて配布するときに参照します.

解決する


現在実行中のプロファイル応答コントローラ

@RestController
@RequiredArgsConstructor
public class ProfileController {

    private final Environment env;

    @GetMapping("/profile")
    public String profile() {
        List<String> profiles = Arrays.asList(env.getActiveProfiles());
        List<String> realProfiles = Arrays.asList("port-1","port-2");
        String defaultProfile = profiles.isEmpty()? "default" : profiles.get(0);

        return profiles.stream()
            .filter(realProfiles::contains)
            .findAny()
            .orElse(defaultProfile);
    }
}

健康診断用ハローコントローラ

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

ドライバサーバのポート情報を含むポート-1、ポート-2プロファイル



application-port-1.properties
server.port=8080
application-port-2.properties
server.port=8081

nginx設定


/etc/nginx/conf.d/semoh-app-api-service-url.inc
set $service_url http://127.0.0.1:8080;
/etc/nginx/sites-enabled/semoh.conf
server {
        listen 80;
        server_name api-test.semoh.co.kr;
        include /etc/nginx/conf.d/semoh-app-api-service-url.inc;

        location / {
                proxy_pass $service_url;

        }
}

配備スクリプト


./start-nostop.sh$env(例./start-nostrop.sh prod)
CURRENT_PORT_PROFILE=$(curl -k http://api-test.semoh.co.kr/profile)

echo "> spring.profiles.active = $1"
if [ -z "$1" ]; then
  echo "profile을 입력하세요. (예: ./start-nostop.sh prod)"
  exit 1
fi

echo "> 현재 구동중인 Port 프로필"
echo "$CURRENT_PORT_PROFILE"

if [ "$CURRENT_PORT_PROFILE" == "port-1" ]; then
  CURRENT_RUNNING_PORT=8080
  WILL_RUNNING_PORT=8081
  WILL_RUNNING_PORT_PROFILE="port-2"
elif [ "$CURRENT_PORT_PROFILE" == "port-2" ]; then
  CURRENT_RUNNING_PORT=8081
  WILL_RUNNING_PORT=8080
  WILL_RUNNING_PORT_PROFILE="port-1"
else
  CURRENT_RUNNING_PORT=8081
  WILL_RUNNING_PORT=8080
  WILL_RUNNING_PORT_PROFILE="port-1"
fi

echo "> 현재 구동중인 Port $CURRENT_RUNNING_PORT"

JAR="./sangsang-noriteo-app-api/build/libs/sangsang-noriteo-app-api-0.0.1-SNAPSHOT.jar"

cd ../../
rm $JAR
./gradlew :sangsang-noriteo-app-api:test
./gradlew :sangsang-noriteo-core:clean
./gradlew :sangsang-noriteo-core:cleanQuerydslSourcesDir
./gradlew :sangsang-noriteo-app-api:bootJar

fuser -k $WILL_RUNNING_PORT/tcp

echo "> 구동 시 Port $WILL_RUNNING_PORT"
echo "> 구동 할 port profile $WILL_RUNNING_PORT_PROFILE"

nohup java -jar -Dspring.profiles.active="$1",$WILL_RUNNING_PORT_PROFILE $JAR &

echo "> Health check 시작합니다."
echo "> curl -s http://localhost:$WILL_RUNNING_PORT/hello"
sleep 3

for retry_count in {1..300}; do
  response=$(curl -s http://localhost:$WILL_RUNNING_PORT/hello)
  up_count=$(echo "$response" | grep -c "hello")

  if [ "$up_count" -ge 1 ]; then
    echo "> Health check 성공"
    break![](https://velog.velcdn.com/images/sonaky47/post/60c08f31-794d-4d6a-a8bf-9f0ad26dd064/image.png)

  else
    echo "> Health check: ${response}"
  fi

  if [ "$retry_count" -eq 100 ]; then
    echo "> Health check 실패. "
    echo "> Nginx에 연결하지 않고 배포를 종료합니다."
    exit 1
  fi

  echo "> Health check 연결 실패. 재시도..."
  sleep 1
done

echo "> 전환할 Port: $WILL_RUNNING_PORT"
echo "> Port 전환"
echo "set \$service_url http://127.0.0.1:$WILL_RUNNING_PORT;" | sudo tee /etc/nginx/conf.d/semoh-app-api-service-url.inc

sudo service nginx reload

sleep 10
echo "> 구동중이었던 프로세스 종료"
fuser -k $CURRENT_RUNNING_PORT/tcp