Skip to content

TIL -2025-05-26 [Spring Actuator 기반 Promql, Grafana 시각화용 추천 PromQL, Spring Boot + Prometheus + Alertmanager + Slack 연동 + 부하 테스트 자동화 예제, Grafana 실습] #75

Description

@soheeGit

📌 Spring Boot Actuator + Micrometer에서 Prometheus와 Grafana로 시각화할 때 실무에서 자주 쓰이는 PromQL 쿼리

1. HTTP 요청 수

sum(rate(http_server_requests_seconds_count[1m])) by (method, status)
  • 최근 1분간의 요청 수를 초당 비율로 집계
  • method, status 별 분류 가능 (GET, POST, 200, 500 등)
  • 트래픽 모니터링, API 사용량 파악에 유용

2. HTTP 요청 평균 응답 시간

sum(rate(http_server_requests_seconds_sum[1m])) by (uri) 
/ 
sum(rate(http_server_requests_seconds_count[1m])) by (uri)
  • 요청별 평균 응답 시간 (초)
  • uri 경로별로 집계 가능
  • 특정 API가 느린지 확인할 때 사용

3. JVM Heap 메모리 사용량

jvm_memory_used_bytes{area="heap"} 
/
jvm_memory_max_bytes{area="heap"}
  • JVM 힙 사용률 (0.0 ~ 1.0 사이)
  • 메모리 누수나 과도한 GC를 감지할 수 있음

4. 활성 스레드 수 (JVM Thread)

jvm_threads_live_threads
  • 현재 활성화된 JVM 스레드 개수
  • 스레드 누수나 고부하 감지에 사용

5. 애플리케이션 가용성 (UP 여부)

up{job="spring-app"}
  • Prometheus에서 수집 가능한지 여부
  • 0이면 애플리케이션이 죽었거나 scrape 실패한 것

📌 Grafana 시각화용 추천 PromQL

카테고리 PromQL 설명 추천 차트
① HTTP 요청 수 sum(rate(http_server_requests_seconds_count[1m])) by (uri) URI별 초당 요청 수 Bar chart, Time series (Lines)
② HTTP 응답 시간 sum(rate(http_server_requests_seconds_sum[1m])) by (uri) / sum(rate(http_server_requests_seconds_count[1m])) by (uri) URI별 평균 응답 시간 (초) Time series, Heatmap
③ JVM 힙 메모리 사용률 jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"} 힙 사용률 (0.0~1.0) Gauge, Time series
④ CPU 사용률 (시스템 전체) 100 - (avg by (instance)(irate(node_cpu_seconds_total{mode="idle"}[1m])) * 100) 노드 전체 CPU 사용률 (%) Time series, Stat panel
⑤ 애플리케이션 상태 up{job="spring-app"} 1: 정상, 0: 다운 Single stat, Table, Status panel

📌 Spring Boot + Prometheus + Alertmanager + Slack 연동 + 부하 테스트 자동화 예제

1. Prometheus 설정 (prometheus.yml)

global:
  scrape_interval: 5s

rule_files:
  - "alert.rules.yml"

scrape_configs:
  - job_name: 'spring-local'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['host.docker.internal:8080']
      # - targets: ['app:8080']

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['host.docker.internal:9093']
  • 5초마다 /actuator/prometheus에서 메트릭 수집
  • alert.rules.yml에 정의된 조건 충족 시 AlertManager(9093)로 알림 발송

2. 알림 조건 정의 (alert.rules.yml)

groups:
  - name: example
    rules:
      - alert: HighRequestRate
        expr: rate(http_server_requests_seconds_count[10s]) > 10
        for: 10s
        labels:
          severity: warning
        annotations:
          summary: "Request rate high"
  • 최근 10초 동안 요청 수가 초당 10건을 초과하면 HighRequestRate 알림 발생
  • 10초간 조건이 유지돼야 알림 전송
  • summary는 Slack에 전달되는 메시지 내용

3. AlertManager 설정 (alertmanager.yml)

route:
  receiver: 'slack-notifications'

receivers:
  - name: 'slack-notifications'
    slack_configs:
      - text: "{{ .CommonAnnotations.summary }}"
        # text: "일어나라!"
        api_url: 'https://hooks.slack.com/services/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'
        channel: 'alert'
        send_resolved: true
  • slack-notifications 수신기로 알림 전송
  • Slack Webhook API를 통해 #alert 채널로 전송
  • 알림 해제(resolved) 시에도 메시지 전송

4. 부하 테스트 스크립트 (test.sh)

#!/bin/bash

# --- 설정 ---
URL="http://localhost:8080/200"  # 테스트할 URL을 입력하세요.
TOTAL_REQUESTS=100000                           # 보낼 총 요청 수를 입력하세요.
CONCURRENT_USERS=5                           # 동시에 실행할 사용자(프로세스) 수를 입력하세요.
OUTPUT_FILE="load_test_results.log"           # 결과(HTTP 상태 코드)를 저장할 파일 이름
# ------------

# 변수 초기화
success_count=0
fail_count=0
request_count=0
pids=() # 백그라운드 프로세스 ID 저장 배열

# 이전 로그 파일 삭제 (선택 사항)
> "$OUTPUT_FILE"

echo "🚀 부하 테스트 시작..."
echo "-----------------------------------"
echo "대상 URL: $URL"
echo "총 요청 수: $TOTAL_REQUESTS"
echo "동시 사용자 수: $CONCURRENT_USERS"
echo "-----------------------------------"

start_time=$(date +%s)

# 요청을 보내는 함수
function send_request {
    local url=$1
    # curl: -s (silent), -o /dev/null (출력 버리기), -w "%{http_code}" (HTTP 상태 코드만 출력)
    http_code=$(curl -s -o /dev/null -w "%{http_code}" "$url")
    echo "$http_code" >> "$OUTPUT_FILE" # 파일에 상태 코드 기록
}

# 총 요청 수에 도달할 때까지 반복
while [ $request_count -lt $TOTAL_REQUESTS ]; do
    # 현재 실행 중인 백그라운드 작업 수 확인
    current_jobs=$(jobs -p | wc -l)

    # 설정된 동시 사용자 수보다 적게 실행 중이고, 총 요청 수에 도달하지 않았다면
    while [ $current_jobs -lt $CONCURRENT_USERS ] && [ $request_count -lt $TOTAL_REQUESTS ]; do
        send_request "$URL" & # 함수를 백그라운드로 실행
        pids+=($!)           # 백그라운드 프로세스 ID 저장
        request_count=$((request_count + 1))
        current_jobs=$(jobs -p | wc -l)
        # 진행 상황 표시 ( \r 을 사용하여 같은 줄에 덮어씀)
        echo -ne "요청 보냄: $request_count / $TOTAL_REQUESTS | 현재 동시 요청: $current_jobs \r"
    done

    # 동시 사용자 수에 도달했다면, 백그라운드 작업 중 하나가 끝날 때까지 기다림
    # -n 옵션: 실행 중인 작업 중 아무거나 하나가 종료되면 즉시 반환
    if [ $current_jobs -ge $CONCURRENT_USERS ]; then
        wait -n
    fi

    # 종료된 프로세스 ID 목록에서 제거 (선택 사항, 더 정확한 관리를 위해)
    # 실제로는 wait -n이 하나씩 처리하므로 이 부분은 단순화 가능
done

# 남아있는 모든 백그라운드 작업이 끝날 때까지 기다림
wait
echo -e "\n-----------------------------------" # 줄바꿈 후 구분선

end_time=$(date +%s)
duration=$((end_time - start_time))

echo "⏳ 모든 요청 완료. 결과 집계 중..."

# 결과 파일 분석
while read -r code; do
    if [[ $code -ge 200 && $code -lt 400 ]]; then
        success_count=$((success_count + 1))
    else
        fail_count=$((fail_count + 1))
    fi
done < "$OUTPUT_FILE"

echo "✅ 부하 테스트 종료."
echo "-----------------------------------"
echo "총 요청 수: $TOTAL_REQUESTS"
echo "성공 요청: $success_count"
echo "실패 요청: $fail_count"
echo "총 소요 시간: $duration"

if [ $duration -gt 0 ]; then
    # bc 계산기를 사용하여 초당 요청 수(RPS) 계산 (소수점 둘째 자리까지)
    rps=$(echo "scale=2; $TOTAL_REQUESTS / $duration" | bc)
    echo "초당 요청 수 (RPS): $rps"
else
    echo "소요 시간이 너무 짧아 RPS를 계산할 수 없습니다."
fi
echo "-----------------------------------"
echo "상세 결과(HTTP 상태 코드)는 $OUTPUT_FILE 파일을 확인하세요."
  • 10만 건의 HTTP 요청을 5개의 프로세스로 병렬 전송
  • 응답 코드별로 성공/실패 카운팅
  • 실행 시간 측정 및 초당 요청 수(RPS) 계산
  • Slack 알림 트리거 실습용으로 매우 유용

5. 컨테이너 실행 명령어

# Prometheus 컨테이너 실행
docker run -d \
  -p 9090:9090 \
  -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
  -v $(pwd)/alert.rules.yml:/etc/prometheus/alert.rules.yml \
  --name prometheus \
  prom/prometheus:latest

# Alertmanager 컨테이너 실행
docker run -d \
  -p 9093:9093 \
  -v $(pwd)/alertmanager.yml:/etc/alertmanager/alertmanager.yml \
  --name alertmanager \
  prom/alertmanager:latest

# 부하 테스트 실행
sh test.sh

# docker rm -f prometheus
# docker restart prometheus
# localhost:9090

# docker rm -f alertmanager
# docker restart alertmanager
# localhost:9093

6. 실습 결과 스크린샷

Image Image Image Image

📌 Grafana 실습 – Prometheus 기반 모니터링 대시보드 구축

1. Grafana 컨테이너 실행

docker run -d -p 3000:3000 grafana/grafana
  • 실행 후 웹 브라우저에서 접속: http://localhost:3000/login
  • 초기 로그인 정보:
    • ID: admin
    • PW: admin (로그인 후 반드시 비밀번호 변경)
Image Image

2. Prometheus 데이터 소스 연결

  • 경로

    • 왼쪽 사이드바 하단 → Connections 클릭 → Data sources → Add data source 선택
  • Prometheus 설정

    • Prometheus 선택 후, 아래처럼 설정
항목
URL http://host.docker.internal:9090
Access Server (default)
Save & Test 클릭하여 연결 테스트
Image Image

3. 대시보드 생성 및 시각화

  • 대시보드 생성
    • 상단 메뉴에서 Dashboard 클릭 → + New → Add visualization
Image
  • 데이터 소스 선택
    • Prometheus 선택
Image
  • 예시 메트릭
    • 메트릭 입력창에 PromQL을 입력 (예: HTTP 요청 수)
rate(http_server_requests_seconds_count[1m])
Image

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions