부하 테스트로 애플리케이션 서버의 임계치를 확인하고 싶어요

shinny·2024년 7월 14일

[성능 개선]

목록 보기
1/8

1️⃣ 필요성

프로젝트를 진행하면서, 여러 방법을 통해 성능 개선을 해나갔다. 그 과정에서 RPS를 개선의 핵심 지표로 사용했고, Redis, MySQL의 CPU 사용량을 중점적으로 보았다. 하지만 애플리케이션 서버 자체에서도 병목 지점은 없는지 등을 애플리케이션 서버의 CPU와 메모리 사용량을 통해 확인해야 할 필요성이 있다고 생각했다.

2️⃣ 애플리케이션 서버 모니터링 시스템 구축

그렇다면, 애플리케이션 서버의 모니터링 시스템 자체가 필요해진다. 개발을 할 때, 로컬 환경에서 간단히 소프트웨어의 Resource Usage를 확인할 수는 있겠지만, 더 정확하게 확인하려면 또 무엇보다 운영 환경에서의 부하 테스트도 진행하기 위해서는 서버 모니터링 시스템 구축이 필요하다.

3️⃣ 방법

3-1. Spring Actuator

Spring Actuator란?
운영 환경에서 앱 모니터링, 지표 수집, 트래픽 감시, 데이터베이스 상태 이해 등을 손쉽게 가능하도록 만들어주는 라이브러리다. Spring Actuator는 앱 실행과 관련된 운영 정보들을 알려주는데, 예를 들어, health, metrics, info, dump, env 등이 있다. 그리고 HTTP 엔드포인트들을 사용해서 이러한 정보들을 제공한다.

우선은 health, info, prometheus의 엔드포인트만 열기를 원했다.
그래서 application.yml에서 다음과 같이 설정해주었다.

  • health : 서버의 구동 여부 제공
  • info : 애플리케이션 관련 정보 제공
  • prometheus : prometheus 관련 정보 제공
management:
  endpoints:
    web:
      exposure:
        include: "health,info,prometheus"
  • {base_url}/actuator

그리고 다음과 같이 spring actuator, prometheus의 라이브러리를 추가해주었다.

implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.micrometer:micrometer-registry-prometheus")

3-2. Prometheus & Grafana

Prometheus

프로메테우스는 메트릭을 수집하고 보관하는 DB 역할을 한다. 다양한 데이터 수집, PromQL이라는 강력한 쿼리 언어를 기반으로 커스텀된 시각화 용이 등 다양한 기능과 장점을 가지고 있다.

  • docker-compose.yml
version: '3.7'

services:
  prometheus:
    image: prom/prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    depends_on:
      - spring-app

Grafana

그라파나는 데이터를 시각화하여 분석 및 모니터링을 용이하게 해주는 오픈소스 분석 플랫폼이다. 데이터독도 있지만 그라파나는 오픈소스이기 때문에 더 활용이 많이 되는 것 같기도 하다. 프로메테우스 같은 데이터 소스를 연동하여 대시보드를 구성할 수 있게 되어 있다. 그라파나 자체가 데이터를 저장하는 것은 아니고, 외부의 데이터소스를 정의하고 연동함으로써, 외부의 데이터 저장소(ex. prometheus)에 쿼리를 날려 결과를 가져온다.

version: '3.7'
volumes:
  grafana-data: {}
  
services:
  grafana:
    image: grafana/grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    logging:
      driver: "json-file"
      options:
        max-size: "8m"
        max-file: "10"
    environment:
      GF_SECURITY_ADMIN_USER: admin
      GF_SECURITY_ADMIN_PASSWORD: admin
      GF_PATHS_PLUGINS: "/var/lib/grafana-plugins"
      GF_INSTALL_PLUGINS: "grafana-clock-panel,grafana-simple-json-datasource"
      GF_LOG_MODE: "console file"
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/plugins:/var/lib/grafana-plugins

3-3. SpringBoot 서버 JVM 정보를 Grafana에서 조회

services:
  spring-app:
    image: eclipse-temurin:21-jdk
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./coupon-api/build/libs/coupon-api.jar:/app.jar
      - /opt/images
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://coupon-mysql:3306/coupon
      SPRING_DATASOURCE_USERNAME: abcd
      SPRING_DATASOURCE_PASSWORD: 1234
      SPRING_REDIS_HOST: coupon-redis
      SPRING_REDIS_PORT: 6380
    command: [ "java", "-jar", "/app.jar" ]
    depends_on:
      - mysql
      - redis
  • prometheus.yml
global:
  scrape_interval: 15s // 15초에 한번 데이터 긁어오기

scrape_configs:
  - job_name: 'spring-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['spring-app:8080']

prometheus가 실행되는 9090 포트에 접속하여 targets를 선택했을 때, UP이라고 되어있는 것을 확인했다면 정상 연결된 것이다.

정리하면, spring actuator를 통해 prometheus의 엔드포인트를 활성화하고 노출시켰고, 그 정보들을 prometheus가 관리하고 수집하고 있다는 것이 확인되었다. 그렇다면 이제 Grafana 대시보드에서 prometheus에서 수집되는 정보들 중 spring-app 서버의 jvm 정보들을 확인할 수 있게 세팅하면 마무리되는 것이다.

3-4. Grafana 대시보드 연결

  • grafana.com으로부터 대시보드를 import할 것이다.

  • dashboard template은 https://grafana.com/grafana/dashboards/4701-jvm-micrometer을 사용할 것이고, datasource는 기존에 등록해둔 prometheus:9090를 연결해줄 것이다.

  • 아래와 같이 jvm micrometer들을 조회할 수 있는 대시보드가 생성되었다.

4️⃣ 평가

  • CPU Usage, JVM Memory, Threads, Thread States, GC Pressure, G1 Eden Space, G1 Old Gen, G1 Survivor Space 등을 모니터링할 수 있다.
  • 부하 테스트를 실시한 뒤, 각 API 별로 스프링 부트 서버에 어느 정도의 부하를 주는지도 확인할 수 있다.
  • synchronized 키워드를 사용한 경우 thread가 얼마나 점유되는지를 통해 서버의 사용량을 예측할 수 있다.

  • docker의 resource usage로 확인해보았을 때, 1000 users, 300 ramp-up으로 설정해서 API 호출 시, cpu usage는 94.54%였다. 최대치는 110%까지 올라갔다.

Reference

  • Spring Boot Actuator(링크)
  • SpringBoot Actuator + Prometheus & Grafana(링크)
profile
꾸준히, 성실하게, 탁월하게 매일 한다

0개의 댓글