주뇽's 저장소

성능테스트를 위한 JMeter 사용 방법(1-2) 시각화 본문

웹개발

성능테스트를 위한 JMeter 사용 방법(1-2) 시각화

뎁쭌 2024. 6. 15. 20:09
728x90
반응형

2024.06.15 - [웹개발] - 성능테스트를 위한 JMeter 사용 방법(1)

 

성능테스트를 위한 JMeter 사용 방법(1)

2024.06.15 - [웹개발] - 성능테스트를 위한 윈도우와 Mac에서 JMeter 설치 방법 성능테스트를 위한 윈도우와 Mac에서 JMeter 설치 방법Apache JMeter는 성능 테스트 및 부하 테스트를 위한 도구로 널리 사용

jypark1111.tistory.com

 

해당 포스팅은 JMeter 사용 방법1에서 나온 결과들을 시각화하는 과정이며 선택사항이다. 

 

0. JMeter, Prometheus, Grafana를 이용한 시각화 작업

성능 테스트는 소프트웨어 개발에서 중요한 부분이다. JMeter를 이용해 성능 테스트를 수행하고, Prometheus와 Grafana를 통해 그 결과를 시각화하여 더욱 효과적으로 데이터를 분석할 수 있다. 아래에서는 각각의 도구에 대한 설명과 사용 이유를 상세히 설명한다.

JMeter란 무엇인가?

JMeter는 Apache에서 개발한 오픈 소스 성능 테스트 도구로서, 웹 애플리케이션의 성능을 테스트하고 분석하는 데 사용한다. 다양한 프로토콜을 지원하며, 스크립트를 작성하여 사용자 행동을 시뮬레이션할 수 있다. 이를 통해 시스템의 병목 현상을 식별하고 성능을 최적화할 수 있다.

Prometheus란 무엇인가?

Prometheus는 SoundCloud에서 개발된 오픈 소스 모니터링 및 경고 도구로서, 시스템의 메트릭 데이터를 수집하고 저장하는 데 사용한다. 시계열 데이터베이스를 기반으로 하며, 강력한 쿼리 언어인 PromQL을 사용해 데이터를 분석할 수 있다. Prometheus를 사용하는 이유는 다음과 같다:

  1. 데이터 수집: 다양한 소스에서 메트릭 데이터를 수집하고 저장한다.
  2. 확장성: 대규모 분산 시스템에서도 높은 성능을 유지한다.
  3. 경고 기능: 특정 조건이 만족될 때 알림을 설정할 수 있다.

Grafana란 무엇인가?

Grafana는 오픈 소스 데이터 시각화 및 모니터링 도구로서, Prometheus와 같은 다양한 데이터 소스와 통합하여 데이터를 시각화한다. 인터랙티브한 대시보드를 제공하여 실시간 데이터를 모니터링하고 분석할 수 있다. Grafana를 사용하는 이유는 다음과 같다:

  1. 사용자 친화적 인터페이스: 직관적인 대시보드로 데이터를 쉽게 시각화한다.
  2. 다양한 플러그인 지원: 여러 데이터 소스와 쉽게 통합할 수 있는 플러그인을 제공한다.
  3. 커스터마이징: 대시보드를 사용자 요구에 맞게 커스터마이징할 수 있다.

JMeter, Prometheus, Grafana를 이용한 시각화 작업 과정

https://www.geeksforgeeks.org/how-to-integrate-jmeter-with-prometheus-and-grafana/

  1. JMeter 설정: JMeter를 이용해 성능 테스트 스크립트를 작성하고 실행한다. 테스트 실행 중에 필요한 메트릭 데이터를 수집한다.
  2. Prometheus 설정: Prometheus를 설치하고, JMeter로부터 데이터를 수집하도록 설정한다. 이를 위해 JMeter 플러그인을 사용하거나, Prometheus Exporter를 이용해 데이터를 수집한다.
  3. Grafana 설정: Grafana를 설치하고, Prometheus를 데이터 소스로 설정한다. 대시보드를 생성하여 Prometheus로부터 수집한 데이터를 시각화한다.

이 과정을 통해 JMeter의 성능 테스트 결과를 실시간으로 모니터링하고 분석할 수 있다. Prometheus와 Grafana를 함께 사용하면, 성능 테스트 데이터를 효과적으로 시각화하고 분석하여 시스템의 성능을 최적화할 수 있다.

 

1. Prometheus, Grafana 설치

Prometheus 설치

Prometheus 설치 방법

  1. Prometheus 다운로드:
    • Prometheus 공식 웹사이트에 접속한다.
    • 'Windows' 플랫폼용 바이너리를 다운로드한다.
    • 다운로드한 압축 파일을 원하는 디렉토리에 압축을 푼다.
  2. Prometheus 실행:
    • 명령 프롬프트를 열고 Prometheus 디렉토리로 이동한다.
    • 아래 명령어를 입력하여 Prometheus를 실행한다:
      prometheus.exe --config.file=prometheus.yml
    • 웹 브라우저에서 http://localhost:9090에 접속하여 Prometheus 웹 UI에 접속할 수 있다.

Grafana 설치

 

  • Grafana 다운로드:
    • Grafana 공식 웹사이트에서 'Windows' 설치 프로그램을 다운로드한다.
    • 다운로드한 설치 프로그램을 실행하여 설치 과정을 진행한다.
  • Grafana 실행:
    • 설치가 완료되면, Grafana 서버를 실행한다. 일반적으로 설치 완료 후 자동으로 실행된다.
    • 웹 브라우저에서 http://localhost:3000에 접속하여 Grafana 웹 UI에 접속할 수 있다.
  • Grafana 설정:
    • 처음 접속 시, 기본 로그인 정보는 사용자명: admin, 비밀번호: admin이다. 처음 로그인하면 비밀번호 변경을 요청받는다.
    • 로그인 후, 'Add data source'를 선택하여 Prometheus를 데이터 소스로 추가한다.
      • Data Sources 메뉴에서 Add data source 버튼을 클릭한다.
      • Prometheus를 선택하고, URL에 http://localhost:9090을 입력한 후 저장한다.

Data Sources 메뉴에서 Add data source 버튼을 클릭한다.
Prometheus를 데이터 소스로 추가한다
URL에 http://localhost:9090을 입력한 후 저장한다.

2. Prometheus와 JMeter 연결

JMeter를 Prometheus에 추가하기 위해서는 Prometheus 설정 파일(prometheus.yml)을 수정하여 JMeter 데이터를 수집하도록 설정해야 한다. 아래는 단계별로 자세히 설명한 내용이다.

1. JMeter 플러그인 설정

먼저, JMeter에서 Prometheus로 데이터를 전송할 수 있도록 JMeter 플러그인을 설정해야 한다.

 

1. https://jmeter-plugins.org/install/Install/ 해당 사이트에서 .jar 파일 다운로드

 

Install :: JMeter-Plugins.org

Installing Plugins The easiest way to get the plugins is to install Plugins Manager. Then you'll be able to install any other plugins just by clicking a checkbox. If you experience any issues with plugins installation, don't hesitate to ask at Support Foru

jmeter-plugins.org

.jar 파일 다운로드

2. 다운로드한 파일을 jmeter폴더의 lib/ext폴더에 추가

 

이후 Jmeter를 재시작하면 우측 상단에 플러그인이 보인다!

우측 상단에 플러그인 설치 확인!

JMeter Prometheus Listener 설치:

  • JMeter에 Prometheus Listener 플러그인을 설치한다. 이는 JMeter의 성능 테스트 결과를 Prometheus 형식으로 노출하는 역할을 한다.
  • JMeter 플러그인 매니저를 열고 'Prometheus Listener'를 검색하여 설치한다.

 

  1. Prometheus Listener 구성:
    • JMeter 테스트 플랜에 'Prometheus Listener'를 추가한다.
    • 'Prometheus Listener'를 추가한 후, 기본 설정을 유지하거나 필요한 설정을 변경할 수 있다. 기본 포트는 9270이다.
    • 쓰레드그룹 -> Add -> Listener 추가 메뉴에서 Prometheus Listener를 추가
    • 프로메테우스 플러그인 깃허브에서 제공하는 아래 이미지를 보고 add 눌러 원하는 정보들을 추가 또는 아래 코드를 .jmx 파일로 저장한 뒤 open을 눌러서 불러오기!
      <?xml version="1.0" encoding="UTF-8"?>
      <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
        <hashTree>
          <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan">
            <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
              <collectionProp name="Arguments.arguments"/>
            </elementProp>
            <boolProp name="TestPlan.functional_mode">false</boolProp>
            <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
          </TestPlan>
          <hashTree>
            <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group">
              <intProp name="ThreadGroup.num_threads">100</intProp>
              <intProp name="ThreadGroup.ramp_time">10</intProp>
              <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
              <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
              <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller">
                <stringProp name="LoopController.loops">10</stringProp>
                <boolProp name="LoopController.continue_forever">false</boolProp>
              </elementProp>
            </ThreadGroup>
            <hashTree>
              <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request">
                <stringProp name="HTTPSampler.domain">localhost</stringProp>
                <stringProp name="HTTPSampler.port">8080</stringProp>
                <stringProp name="HTTPSampler.path">/api/v1/category/popular-posts/100</stringProp>
                <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
                <stringProp name="HTTPSampler.method">GET</stringProp>
                <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
                <boolProp name="HTTPSampler.postBodyRaw">false</boolProp>
                <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
                  <collectionProp name="Arguments.arguments"/>
                </elementProp>
              </HTTPSamplerProxy>
              <hashTree/>
              <com.github.johrstrom.listener.PrometheusListener guiclass="com.github.johrstrom.listener.gui.PrometheusListenerGui" testclass="com.github.johrstrom.listener.PrometheusListener" testname="Prometheus Listener" enabled="true">
                <collectionProp name="prometheus.collector_definitions">
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_sumary</stringProp>
                    <stringProp name="collector.type">SUMMARY</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="50511102">category</stringProp>
                      <stringProp name="102727412">label</stringProp>
                      <stringProp name="3059181">code</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets">0.9,0.1|0.95,0.1|0.99,0.01</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_count_total</stringProp>
                    <stringProp name="collector.type">COUNTER</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="102727412">label</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets"></stringProp>
                    <stringProp name="listener.collector.measuring">CountTotal</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_success_total</stringProp>
                    <stringProp name="collector.type">COUNTER</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="50511102">category</stringProp>
                      <stringProp name="102727412">label</stringProp>
                      <stringProp name="3059181">code</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets"></stringProp>
                    <stringProp name="listener.collector.measuring">SuccessTotal</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_rsize</stringProp>
                    <stringProp name="collector.type">HISTOGRAM</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="102727412">label</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets">100,500,1000,3000</stringProp>
                    <stringProp name="listener.collector.measuring">ResponseSize</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_success_ratio</stringProp>
                    <stringProp name="collector.type">SUCCESS_RATIO</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="102727412">label</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets"></stringProp>
                    <stringProp name="listener.collector.measuring">SuccessRatio</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_latency</stringProp>
                    <stringProp name="collector.type">SUMMARY</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="102727412">label</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets">100,500,1000,3000</stringProp>
                    <stringProp name="listener.collector.measuring">Latency</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_idle_time</stringProp>
                    <stringProp name="collector.type">SUMMARY</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="102727412">label</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets">0.9,0.1|0.95,0.1|0.99,0.01</stringProp>
                    <stringProp name="listener.collector.measuring">IdleTime</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_failure_total</stringProp>
                    <stringProp name="collector.type">COUNTER</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="50511102">category</stringProp>
                      <stringProp name="102727412">label</stringProp>
                      <stringProp name="3059181">code</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets"></stringProp>
                    <stringProp name="listener.collector.measuring">FailureTotal</stringProp>
                  </elementProp>
                  <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
                    <stringProp name="collector.help">default help string</stringProp>
                    <stringProp name="collector.metric_name">jmeter_connet_time</stringProp>
                    <stringProp name="collector.type">COUNTER</stringProp>
                    <collectionProp name="collector.labels">
                      <stringProp name="102727412">label</stringProp>
                    </collectionProp>
                    <stringProp name="collector.quantiles_or_buckets"></stringProp>
                    <stringProp name="listener.collector.measuring">ConnectTime</stringProp>
                  </elementProp>
                </collectionProp>
              </com.github.johrstrom.listener.PrometheusListener>
              <hashTree/>
              <ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report">
                <boolProp name="ResultCollector.error_logging">false</boolProp>
                <objProp>
                  <name>saveConfig</name>
                  <value class="SampleSaveConfiguration">
                    <time>true</time>
                    <latency>true</latency>
                    <timestamp>true</timestamp>
                    <success>true</success>
                    <label>true</label>
                    <code>true</code>
                    <message>true</message>
                    <threadName>true</threadName>
                    <dataType>true</dataType>
                    <encoding>false</encoding>
                    <assertions>true</assertions>
                    <subresults>true</subresults>
                    <responseData>false</responseData>
                    <samplerData>false</samplerData>
                    <xml>false</xml>
                    <fieldNames>true</fieldNames>
                    <responseHeaders>false</responseHeaders>
                    <requestHeaders>false</requestHeaders>
                    <responseDataOnError>false</responseDataOnError>
                    <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
                    <assertionsResultsToSave>0</assertionsResultsToSave>
                    <bytes>true</bytes>
                    <sentBytes>true</sentBytes>
                    <url>true</url>
                    <threadCounts>true</threadCounts>
                    <idleTime>true</idleTime>
                    <connectTime>true</connectTime>
                  </value>
                </objProp>
                <stringProp name="filename"></stringProp>
              </ResultCollector>
              <hashTree/>
            </hashTree>
          </hashTree>
        </hashTree>
      </jmeterTestPlan>

2. Prometheus 설정 파일(prometheus.yml) 수정

Prometheus 설정 파일을 수정하여 JMeter 데이터를 수집하도록 구성한다.

  1. Prometheus 설정 파일 열기:
    • prometheus.yml 파일을 텍스트 편집기로 연다.
    • scrape_configs 섹션에 JMeter의 메트릭 데이터를 수집하도록 설정을 추가한다. 아래 예제에서는 기본 포트 9270을 사용한다.scrape_configs 섹션에 JMeter 추가:
  2. prometheus.yml 파일 예시:
global:
  scrape_interval: 15s # 기본 스크래핑 간격 설정

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'jmeter'
    static_configs:
      - targets: ['localhost:9270']  # JMeter 플러그인을 통한 데이터 수집

3. Prometheus 실행 및 확인

  1. Prometheus 실행:
    • Prometheus를 시작하거나 재시작하여 변경된 설정을 적용한다.
    • 명령 프롬프트를 열고 Prometheus가 설치된 디렉토리로 이동한 후 아래 명령어를 입력한다:
      prometheus.exe --config.file=prometheus.yml
  2. 데이터 수집 확인:
    • 웹 브라우저에서 http://localhost:9090에 접속하여 Prometheus 웹 UI에 접속한다.
    • 'Status' 메뉴에서 'Targets'를 클릭하여 JMeter 메트릭이 정상적으로 수집되고 있는지 확인한다. 'Targets' 페이지에 'jmeter'가 있고, 상태가 'UP'으로 표시되면 성공적으로 설정된 것이다.

 

4. Grafana에서 JMeter 데이터 시각화

  1. Grafana 설정:
    • 웹 브라우저에서 http://localhost:3000에 접속하여 Grafana 웹 UI에 접속한다.
    • 로그인 후, 'Data Sources' 메뉴에서 Prometheus를 데이터 소스로 추가한다. (이미 설정된 경우 이 단계는 생략 가능)
  2. 새 대시보드 생성:
    • 'Create' 메뉴에서 'Dashboard'를 선택하여 새 대시보드를 생성한다.
    • 'Add visualization'을 클릭하여 새로운 패널을 추가한다.
  3. JMeter 메트릭 시각화:
    • 패널 설정에서 Prometheus 쿼리를 입력하여 JMeter 메트릭 데이터를 시각화한다. 예를 들어, jmeter_threads_active와 같은 메트릭을 사용할 수 있다.
    • 필요한 시각화 유형을 선택하고 패널을 저장한다.