블루-그린 무중단 배포에서 Downtime을 측정해보자

2025. 5. 12. 20:06·💻 개발

1. 개요

이전에 "프리티어에서 블루-그린 무중단 배포를 해보자"라는 주제로 글을 작성했었는데요. 그 글의 결론 부분에서 Nginx가 Reload될 때 약 0.1초의 다운타임이 존재한다고 언급했습니다.

 

2025.03.16 - [💻 개발] - 프리티어에서 블루-그린 무중단 배포를 해보자

 

하지만 제가 이 수치를 어떻게 도출했는지 명확하게 설명하지 않았더라고요. 이번 글에서는 JMeter를 사용하여 실제로 Nginx Reload 시 발생하는 다운타임을 어떻게 측정했는지, 그리고 그 결과는 어떻게 나왔는지 분석해봤습니다.

 

JMeter란?

JMeter는 Apache 재단에서 개발한 오픈 소스 테스트 도구입니다. 웹 애플리케이션의 성능을 테스트하고 분석하는 데 자주 사용되며, "부하 테스트를 한다!" 라고 했을 때 가장 먼저 언급되는 도구인 것 같아요.

 

기존에 간단한 부하테스트를 진행하고자 할 때 저는 그냥 Postman을 사용했었는데요. Postman에서는 Virtual Users를 최대 100명까지만 추가할 수 있기도 하고, 세부적인 사항을 설정하기에도 한계가 명확해서 이번에 한번 JMeter를 써봤습니다.

 

추가적인 JMeter에 대한 정보는 이 블로그 글에서 자세하게 설명하고있는 것 같아요.

2. 측정에 사용한 API

측정을 위해 Spring Actuator에서 제공하는 /actuator/health 경로를 사용했습니다. Downtime을 측정하기 위한 API를 선택할 때는 최대한 비즈니스 로직이 없고, 서버가 응답 가능한 상태가 되었을 때 바로 응답하는 API를 사용하는 것이 중요하다고 생각했기 때문입니다.

 

해당 API를 선택한 이유를 정리하면 다음 3가지가 존재했습니다.

  • 간단한 응답 (JSON 형식의 간단한 상태 정보)
  • 별도의 비즈니스 로직 처리나 데이터베이스 접근이 없음
  • 애플리케이션의 실제 가용성을 정확하게 반영 (실제로 서버가 API를 처리할 수 있어야 함)

 

이 요청은 애플리케이션이 정상적으로 동작 중일 때 다음과 같은 응답을 반환합니다.

{
  "status": "UP"
}

3. JMeter 테스트 구성

JMeter로 다운타임을 측정하기 위해 다음과 같이 테스트를 구성했습니다:

1) 스레드 그룹 설정

  • 스레드 수(Number of Threads): 100
    • 최대 100명의 사용자가 요청을 보내는 상황을 테스트할 수 있습니다.
  • 램프업 시간(Ramp-up period): 1초
    • 100개의 스레드를 1초 이내에 모두 시작합니다.
  • 반복 횟수(Loop Count): Infinity
    • 수동으로 테스트를 종료할 때까지 반복합니다.
  • 필요 시 스레드 생성 지연(Delay Thread creation until needed): 체크
    • 필요할 때만 스레드를 생성해서 리소스 사용을 최적화합니다.

2) HTTP 요청 설정

  • 프로토콜: HTTPS
  • 서버명/IP: 본인의 서버 IP or Domain
  • 경로: /actuator/health
  • HTTP 메서드: GET
  • Keep-Alive 사용(Use KeepAlive): True
    • HTTP 연결을 재사용합니다. 연결 설정에서의 오버헤드를 줄입니다.

테스트 대상 서버에 Spring Actuator의 health 엔드포인트로 지속적인 요청을 보내도록 설정했습니다.

3) 처리량 제어 타이머

  • 목표 처리량(Target throughput): 6000.0 샘플/분
    • 분당 6000개의 샘플링을 진행합니다. 초당 100개의 요청을 보내기 위해 노력합니다.
  • 처리량 계산 기준(Calculate Throughput based on): 현재 스레드만(this thread only)
    • 스레드 각각이 초당 100개를 보내기 위해 노력하기 때문에, 이론상 최대 초당 1만개의 요청까지 보낼 수 있습니다.

최대한 많은 요청을 보내도록 설정하여 요청을 보낸 시간을 가능한 많이 세분화할 수 있도록 했습니다.

4. 측정 방법

JMeter를 사용하여 다음과 같은 방식으로 테스트를 진행했습니다:

  1. 위에서 구성한 JMeter 테스트 계획을 실행하여 지속적으로 /actuator/health 엔드포인트에 요청을 보냅니다.
  2. 테스트가 안정적으로 실행되고 있는 것을 확인한 후, 수동으로 무중단 배포 스크립트를 실행합니다.
  3. JMeter의 결과 창에서 에러가 발생한 구간을 확인합니다.
  4. 에러 직전의 마지막 성공 응답 시간과 에러 이후 첫 번째 성공 응답 시간의 차이를 계산하여 다운타임을 측정합니다.

 

이 과정을 총 5회 반복하여 평균 다운타임과 편차를 분석했습니다.

5. 측정 진행 결과 (총 5회 진행)

5차 테스트 진행 결과
5회동안의 Downtime 통계
5회동안의 Downtime 그래프

분석 요약

5회의 테스트를 통해 얻은 결과를 분석해보면 다음과 같습니다.

  • 평균 다운타임: 0.039초
  • 최소 다운타임: 0.017초 (1차 테스트)
  • 최대 다운타임: 0.086초 (2차 테스트)
  • 2차 테스트의 다운타임이 다른 테스트보다 약 3.2배 높게 나타났지만, 모두 0.1초 이내에 완료된 것을 확인할 수 있습니다.

 

원인 분석

이 배포 과정 중 발생한 Downtime의 원인은 바로 Keep-Alive 옵션 때문입니다. Keep-Alive가 활성화된 경우, 클라이언트와 서버 간 TCP 연결이 여러 요청이 진행되는동안 유지되면서 더 빠른 데이터 전송이 가능하게 하는데요. 이 때 Nginx 리로드를 하게되면 기존 연결이 모두 종료되면서 Half-Close 상태로 들어가게 되는데요. 이런 상황은 서버에서는 연결을 종료했지만 클라이언트에서 FIN을 보내기 전까지는  클라이언트에서 오는 데이터를 받을 수는 있는 상태가 됩니다. 이 때문에 Nginx가 Reload되는 과정에서는 Half Close 상태에서 클라이언트가 서버로 보내는 요청을 받을 수 없기 때문에 서버 에러가 발생하게 되는 거라고 볼 수 있습니다.

 

실제로 JMeter에서 Keep-Alive를 해제하고 테스트를 진행하면, Downtime이 존재하지 않는 현상을 관찰할 수 있습니다.

자세한 내용은 여기와 여기에서 상세하게 설명하고 있으니 궁금하신 분들은 보시면 좋을 것 같아요!

 

6. 결론

이번 측정을 통해 Nginx Reload 시 발생하는 실제 다운타임은 이전에 언급했던 0.1초보다 더 짧은 평균 0.039초로 볼 수 있습니다. 이는 Spring Actuator의 단순한 health 엔드포인트를 사용하여 측정한 결과로, 실제 비즈니스 로직이 포함된 복잡한 API에서는 다운타임이 약간 더 길어질 수 있습니다. (응답을 위한 비즈니스 로직 처리 시간이 존재하기 때문)

 

이러한 결과를 통해 Nginx를 활용한 블루-그린 배포 방식이 "무중단"이라는 표현보다는 "최소 중단" 배포 방식이라고 표현하는 것이 더 정확하다고 볼 수 있습니다. 그럼에도 평균 0.039초라는 다운타임은 대부분의 서비스에서 사용자가 체감하기 어려운 수준이기 때문에 "무중단"이라고도 할 수 있을 것 같습니다.

 

또한 이 Downtime이 발생하게 된 이유가 Keep-Alive로 인한 결과라고도 짧게 분석해봤는데요. 이를 통해 Keep-Alive 옵션을 끄고 서버를 동작시키면 Downtime을 아예 발생시키지 않을 수도 있으나, 매 요청마다 새로운 TCP 연결을 생성해야 하기 때문에 서버와 클라이언트 모두 오버헤드가 생기기 때문에 권장되지는 않습니다. Downtime을 아예 없애는게 좋긴 하지만, 이를 없애기 위해서 Keep-Alive를 희생시키는 것은 너무 큰 손해이기 때문이죠.

 

이렇게 Downtime을 측정해보고, 분석해보았습니다. 0.04초정도의 평균 Downtime이 존재하지만, 여기서 더 개선하기보단 지금 상황을 유지하는 것이 더 합리적인 선택이라고 생각합니다.

'💻 개발' 카테고리의 다른 글

프리티어에서 블루-그린 무중단 배포를 해보자  (0) 2025.03.16
FastAPI 프로젝트에 Ruff 포맷팅을 적용해보자  (0) 2025.02.03
Spring Boot에서 DB에 초기 데이터를 넣어보자  (0) 2025.02.02
@OneToOne 연관에서 발생한 N+1 문제를 해결하자  (0) 2025.01.17
Spring Boot에서 Sentry가 쿼리를 추적하게 해보자  (1) 2025.01.13
'💻 개발' 카테고리의 다른 글
  • 프리티어에서 블루-그린 무중단 배포를 해보자
  • FastAPI 프로젝트에 Ruff 포맷팅을 적용해보자
  • Spring Boot에서 DB에 초기 데이터를 넣어보자
  • @OneToOne 연관에서 발생한 N+1 문제를 해결하자
가디(Gadi)
가디(Gadi)
dev-gadi 님의 블로그 입니다.
  • 가디(Gadi)
    진짜 개발용 블로그
    가디(Gadi)
  • 전체
    오늘
    어제
    • 분류 전체보기 (9)
      • 💻 개발 (6)
      • 🤔 회고 (3)
  • 태그

    Query
    CLF
    회고
    CI/CD
    글또
    FastAPI
    트러블슈팅
    Ruff
    블루-그린
    SQL
    자격증
    티끌
    N+1
    isort
    쉘 스크립트
    springboot
    AWS
    무중단 배포
    downtime
    측정
    BLACK
    formatting
    jmeter
    2025
    Sentry
    마무리
    Python
    log
    코지메이트
  • 공지사항

  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
가디(Gadi)
블루-그린 무중단 배포에서 Downtime을 측정해보자
상단으로

티스토리툴바