nGrinder
nGrinder 설치
nGrinder 깃허브 설치 링크: https://github.com/naver/ngrinder/releases
- 위 링크 접속 후 원하는 버전의 nGrinder의 war 파일 설치
- 설치된 war 파일이 있는 디렉토리로 가서 다음의 명령어를 통해 war 파일 실행 -> nGrinder-Controller 구동
- java -Djava.io.tmpdir=/Users/${username}/${생성할 파일명} -jar [파일명].war --port=${포트} // ex) java -Djava.io.tmpdir=lib -jar ngrinder-controller-3.5.9-p1.war --port=8300
- 이후 localhost:${설정한포트}로 접속한 후, 아이디와 비밀번호 각각 admin을 입력하여 로그인
- admin을 눌러 Download Agent를 통해 Agent를 다운받고 압축을 푼 후, nGrinder-Controller가 있는 폴더에 함께 위치시켜준다.
- 터미널에서 압축을 풀어준 폴더로 이동한 뒤, agent를 실행 시켜준다
- ./run_agent.sh // mac ./run_agent.bat // window
- 다시 localhost:${설정한포트}로 접속해서 admin 클릭 후, Agent Management탭으로 이동하면 정상적으로 agent가 하나 켜져있는 것을 볼 수 있다.
- 주의본인도 JDK 17을 쓰다가 에러가 발생해서 asdf를 통해 자바 버전을 11로 맞춰주었는데, 여기서도 무수히 많은 에러가 있었다..
- 이전에 brew를 통해 다운받은 jdk와 asdf로 다운받은 jdk의 충돌, ~/.zshrc에서 PATH 설정 변경 등을 통해 해결했다..!
- nGrinder는 현재 JDK8과 JDK 11까지만 지원을 하기 때문에 자바 버전을 제대로 맞춰주어야 한다..
nGrinder 사용법
- 좌측 상단에 Script 탭 클릭 후 create 클릭
- 만약, Script 클릭이 안되고 Error while fetching files from SVN for admin 에러 발생 시, ~ 위치에서 sudo rm -r .ngrinder 실행 후 다시 controller 부팅
- 이름과 경로를 입력한 후, 생성
- validate를 눌러 검증 -> 성공 시, Save를 눌러 스크립트 저장
- Performance Test 탭으로 이동 후 create test 버튼 클릭
- Agent=1, Vuser=?, Script=?, Duration=? 설정해준 후 Start
nGrinder 용어
- TPS(처리량)
- Transactinos Per Second의 약어로, "초당 처리가능한 트랜잭션의 수"
- TPS가 100이라면 초당 처리할 수 있는 작업의 수가 100이라고 생각하면 된다
- TPS 수치가 높을수록 짧은 시간에 많은 작업을 처리할 수 있다
- Vuser
- 가상 사용자(Virtual User)
- ex) "Vuser 10"은 가상 사용자가 10명임을 나타낸다. 이것은 부하테스트 시나리오에서 10명의 가상 사용자가 동시에 시스템 또는 애플리케이션에서 동작하고 있다는 것을 의미한다.
퍼포먼스 테스트 결과창에서의 용어
- TPS: 주어진 시간동안 테스트했을 때 평균 TPS
- Peak TPS: 최고 TPS
- Mean Test Time: 하나의 작업을 처리하는데 걸린 평균 테스트 시간
- Executed Tests: 테스트 실행 횟수
- Successful Tests: 테스트 성공 횟수
- Errors: 에러 횟수
- Run time: 테스트 실행 시간
⇒ TPS가 높고 Mean Test Time이 낮을 수록 긍정적이다.
수많은 모니터링 툴들이 있지만 대세이면서도 자료가 가장 많은 prometheus + grafana 조합을 사용해보도록 하겠다!
스프링 액츄에이터
스프링 액츄에이터는 지표, 추적, 감사, 모니터링 등과 같은 프로덕션 레디 기능을 매우 편리하게 사용할 수 있는 다양한 편의 기능을 제공해주는 라이브러리이다. 더 나아가 다양한 모니터링 시스템과 매우 쉽게 연동할 수 있는 기능을 제공한다. 다음을 build.gradle에 추가해주자
implementation 'org.springframework.boot:spring-boot-starter-actuator'
이렇게 추가만해도 ‘/actuator’라는 경로를 통해 접근하면 수많은 엔드포인트를 통해 기능을 제공한다는 것을 확인할 수 있다.
우리는 shutdown을 제외한 모든 기능을 활성화 및 노출시켜 주기 위해 다음과 같이 application.yml을 작성한다.
management:
server:
port: 9292
info:
java:
enabled: true
os:
enabled: true
endpoint:
health:
show-details: ALWAYS
endpoints:
web:
exposure:
include: "*"
- management.server.port를 통해 별도의 포트에서 액츄에이터 엔드포인트를 제공한다
- management.info.java.enabled + management.info.os.enabled → java와 os에 대한 정보도 제공한다
- management.endpoint.health.show-details → health 체크 시 더 자세한 정보를 제공한다
- management.endpoints.web.exposure.include=”*” → 활성화된 모든 기능을 노출한다.
- shutdown 기능은 자동 활성화되어 있지 않으므로 노출되지 않는다.
마이크로미터
스프링 액츄에이터를 통해 수많은 매트릭들을 수집할 수 있지만, 이는 일시적인 값들이며 과거의 이력들을 확인할 수 없다는 단점이 있다. 또한, 모두 객체 형태로 데이터를 보여주기에 시각화하기 위한 별도의 툴들이 반드시 필요하다.
여기서 또 다른 문제는 수많은 모니터링 툴들이 있는데, 같은 정보를 수집하더라도 어떤 툴을 사용하느냐에 따라 전달해주어야 하는 데이터의 형식이 다르다. 수많은 지표들을 모니터링 툴에 맞도록 만들어서 보내주어야 하는데, 만약 모니터링 툴을 변경하게 된다면 지표에 관한 코드들을 모두 변경해야 하는 불상사가 발생할 것이다.
이런 문제를 해결하기 위해 마이크로미터(Micrometer)라는 라이브러리를 사용한다!
마이크로미터는 애플리케이션 메트릭 파사드라고 불리는데, 애플리케이션의 메트릭을 마이크로미터가 정한 표준 방법으로 모아서 제공한다. 쉽게 이야기해서 마이크로미터가 추상화를 통해 구현체를 쉽게 갈아끼울 수 있도록 해두었다.
스프링 부트 엑츄에이터는 마이크로미터를 기본으로 내장해서 사용하기에 별도로 추가해줄 필요는 없다.
개발자는 이제 마이크로미터가 정한 표준방법으로 메트릭을 전달한 후, 구현체만 정해주면 된다. 이 메트릭을 모니터링 툴에 맞게 변환해주는 작업은 마이크로미터가 알아서 해줄것이다!
우리는 모니터링 툴로서 프로메테우스를 사용할 것이므로 다음의 라이브러리를 추가한다!
// micrometer-prometheus
implementation 'io.micrometer:micrometer-registry-prometheus'
이제 localhost:9292/actuator/prometheus라는 엔드포인트에 접근 가능하다!
프로메테우스 & 그라파나 설정
프로메테우스와 그라파나
애플리케이션에서 발생한 수많은 매트릭을 장기적으로 수집 및 관리하고 모니터링 하기 위해서는 이를 저장할 데이터베이스가 필요하다. 프로메테우스는 이를 담당한다.
프로메테우스 자체도 그래프를 보여주고 시간대를 설정하여 과거 이력을 확인할 수도 있지만, 한눈에 들어오는 대시보드를 만들어보기 어려우며, 매번 프로메테우스에서 사용하는 쿼리를 통해 조회를 해야 한다는 단점이 있다.
이러한 단점은 그라파나를 통해 해결하 수 있다! 그라파나는 프로메테우스를 통해서 데이터를 조회하고 보여주는 역할을 한다. 쉽게 이야기하면 그라파나는 대시보드의 껍데기 역할을 한다.
직접 툴을 설치할 수도 있겠지만, 여기서는 docker를 통해 설정해보자!
Docker 설정
Dockerfile
# Start with an OpenJDK base image
FROM openjdk:17-jdk-slim
# Set the working directory in the container
WORKDIR /app
# Copy the built jar file into the container
COPY todomon-core/build/libs/todomon-app.jar /app/todomon-app.jar
# Expose the port that the application will run on
EXPOSE 8080
# Run the jar file when the container starts with Pinpoint agent
ENTRYPOINT ["java", "-jar", "/app/todomon-app.jar"]
- todomon-core 모듈에 있는 jar 파일을 실행하는 이미지를 만든다.
- docker build -t todomon-app . 이라는 명령어를 프로젝트 루트에서 실행시키면 todomon-app이라는 도커 이미지가 생성된다.
docker-compose.yml
services:
mysql:
image: mysql:8.0
container_name: mysql-container
environment:
MYSQL_ROOT_PASSWORD: 1234 # MySQL root 계정의 비밀번호
MYSQL_DATABASE: todomon # 초기 생성할 데이터베이스 이름
MYSQL_CHARSET: utf8mb4 # 기본 charset을 utf8mb4로 설정
MYSQL_COLLATION: utf8mb4_unicode_ci # 기본 collation을 utf8mb4_unicode_ci로 설정
TZ: Asia/Seoul
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- "3305:3306" # 호스트의 3306 포트를 컨테이너의 3306 포트와 연결
volumes:
- mysql_data:/var/lib/mysql # 데이터를 지속하기 위한 볼륨 설정
networks:
- spring-mysql-network
todomon-app:
image: todomon-app
container_name: todomon-app-container
ports:
- "8080:8080"
- "9292:9292"
volumes:
- ./todomon-core/build/libs/todomon-app.jar:/app/todomon-app.jar # JAR 파일을 컨테이너에 매핑
networks:
- spring-mysql-network
depends_on:
- mysql
prometheus:
image: prom/prometheus:latest
container_name: prometheus-container
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
- spring-mysql-network
depends_on:
- todomon-app
grafana:
image: grafana/grafana:latest
container_name: grafana-container
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
networks:
- spring-mysql-network
depends_on:
- prometheus
networks:
spring-mysql-network:
driver: bridge
volumes:
mysql_data:
grafana_data:
- 프로메테우스는 localhost:9090을 통해 접근 가능하다.
- 그라파나는 localhost:3000을 통해 접근 가능하다.
- 접근 시 로그인 화면이 뜨는데 아이디와 비밀번호는 모두 admin이다.
- 운영 환경이 아니니 굳이 비밀번호를 변경하지 말자.. ㅋㅋ
주의
스프링 애플리케이션의 DB url도 제대로 설정해주어야 한다. 위 설정에 따르면 url은 다음과 같아야 한다.
jdbc:mysql://mysql-container:3306/todomon
prometheus.yml 작성
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: [ "localhost:9090" ]
- job_name: 'spring-boot-actuator'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: [ 'todomon-app:9292' ] # Spring Boot 앱의 컨테이너 또는 호스트 주소
- 프로메테우스가 우리 애플리케이션의 /actuator/prometheus를 호출해서 메트릭을 주기적으로 수집하도록 설정해야 한다. 이를 위해서 prometheus.yml을 위처럼 작성한다.
- todomon-app이라는 컨테이너의 9292 포트로 엑츄에이터 엔드포인트가 제공되므로 위처럼 설정한다.
- scrape_interval 여기서는 수집 주기를 15s 로 했지만, 수집 주기의 기본값은 1m 이다.
- 수집 주기가 너무 짧으면 애플리케이션 성능에 영향을 줄 수 있으므로 운영에서는 10s ~ 1m 정도를 권장한다. (물론 시스템 상황에 따라서 다르다.)
모두 작성이 되었다면 docker-compose up -d 명령어를 통해 컨테이너가 잘 뜨는지 확인하자!
확인사항
- 프로메테우스에 접속해서 상단 메뉴 Status → Targets 에 들어가서 연동이 잘 되었는지 확인
- prometheus: 프로메테우스 자체에서 제공하는 메트릭정보이다. (프로메테우스가 프로메테우스 자신의 메트릭을 확인하는 것이다.)
- spring-boot-actuator: 우리가 연동한 애플리케이션의 메트릭 정보이다. (prometheus.yml에서 설정해주었다)
2. 그라파나 우측 메뉴에서 Connections → Data sources에 들어가서 프로메테우스 데이터 소스 설정
그라파나 공유 대시보드 추가
그라파나 공유 대시보드 사이트: https://grafana.com/grafana/dashboards
위 사이트에서 spring이라고 검색해서 유용한 대시보드들의 아이디를 복사한 후, 우리의 그라파나 대시보드에 추가할 수 있다!
- 스프링 부트 시스템 모니터 대시보드: https://grafana.com/grafana/dashboards/11378-justai-system-monitor/ (ID: 11378)
- 마이크로미터 대시보드: https://grafana.com/grafana/dashboards/4701-jvm-micrometer/ (ID: 4701)
위 2가지를 추가해주자!
이후 스프링부트 시스템 모니터 대시보드에 몇가지 수정사항이 있다! 대시보드를 수정하려면 먼저 수정모드로 변경해야 한다.
대시보드에 들어가서 설정 버튼을 누르고, Make editable 선택
이후 다음과 같이 수정
- Jetty 통계 → Tomcat 통계
- 이 대시보드는 톰캣이 아니라 Jetty라는 웹 서버를 기준으로 통계를 수집한다.
- 이 부분을 수정하자.Jetty Statistics 부분으로 이동한 다음 설정 버튼을 통해 Title을 Tomcat Statistics로 변경한다.
- Thread Config Max 패널 설정 변경
- jetty_threads_config_max → tomcat_threads_config_max_threads로 변경
- Thread 패널 설정 변경
- jetty_threads_current → tomcat_threads_current_threads
- jetty_threads_busy →tomcat_threads_busy_threads
- jetty_threads_idle 제거
- jetty_threads_jobs 제거
이렇게 Docker와 Prometheus + Grafana로 전체 시스템을 조망하는 모니터링 시스템을 구성해보았다!
'Project' 카테고리의 다른 글
[TODOMON] EP.10 캐싱을 통한 전체 & 소셜 랭킹 조회 API 개선하기 w/ Redis (1) | 2025.02.04 |
---|---|
[TODOMON] EP.9 부하 테스트 진행(야매) (0) | 2025.02.04 |
[TODOMON] EP.7 부하 테스트 계획 (0) | 2025.02.03 |
[TODOMON] Ep.6 Spring Batch 도입기 (+ 멀티스레드를 통한 성능 개선까지) (0) | 2025.02.02 |
[TODOMON] EP.5 견고한(?)결제 시스템 구축기.. with 포트원 (2) | 2025.01.31 |