JMeter Kurulumu ve Temel Yük Testi Senaryoları

Yük testi denince aklıma hep o bir production krizi gelir: Saat 03:00, telefon çalıyor, e-ticaret sitesi çökmüş, Black Friday trafiği sistemi yerle bir etmiş. O gece sabaha kadar log okuduk, metrik inceledik ve sonunda şu soruyu sorduk kendimize: “Bunu önceden neden test etmedik?” İşte o geceden sonra JMeter hayatımın ayrılmaz bir parçası oldu.

JMeter, Apache tarafından geliştirilen, Java tabanlı, açık kaynak bir yük testi aracı. Hem GUI hem de komut satırı modunda çalışabiliyor. k6 veya Locust kadar modern görünmeyebilir ama kurumsal ortamlarda, özellikle Java ekosistemiyle çalışan ekiplerde hala birinci tercih. Neden? Çünkü test planlarını XML olarak saklıyor, CI/CD pipeline’larına kolayca entegre edilebiliyor ve çok geniş bir plugin ekosistemi var.

Ortam Hazırlığı ve Kurulum

JMeter Java gerektiriyor. Java 8 veya üzeri çalışıyor ama ben her zaman LTS sürümlerini tercih ederim. Önce Java kurulumunu halledelim.

# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-17-jdk -y

# Java versiyonunu doğrula
java -version

# RHEL/CentOS/AlmaLinux
sudo dnf install java-17-openjdk -y

Java kurulduktan sonra JMeter’ı indirip kuralım. Ben her zaman official Apache mirror’larını kullanırım, random sitelerden indirmekten kaçının.

# JMeter indirme (güncel sürümü kontrol edin: https://jmeter.apache.org/download_jmeter.cgi)
wget https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz

# Arşivi aç
tar -xzf apache-jmeter-5.6.3.tgz

# Uygun bir konuma taşı
sudo mv apache-jmeter-5.6.3 /opt/jmeter

# Kullanım kolaylığı için symlink oluştur
sudo ln -s /opt/jmeter/bin/jmeter /usr/local/bin/jmeter

# Çalıştırma izni ver
sudo chmod +x /opt/jmeter/bin/jmeter

# Doğrula
jmeter --version

JAVA_HOME değişkenini de ayarlamak iyi bir alışkanlık. Özellikle birden fazla Java sürümü kuruluysa karışıklık yaşanabiliyor.

# ~/.bashrc veya ~/.profile dosyasına ekle
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
export JMETER_HOME=/opt/jmeter
export PATH=$JMETER_HOME/bin:$PATH

# Değişiklikleri uygula
source ~/.bashrc

JMeter Heap Memory Ayarı

Bu adımı atlayanların yük testlerinin yarısında JMeter kendisi çöker. Default heap size çoğu senaryo için yetersiz.

# /opt/jmeter/bin/jmeter dosyasını düzenle
# Şu satırı bul ve değiştir:
# : "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"

# Daha iyi bir değer için:
export HEAP="-Xms2g -Xmx4g -XX:MaxMetaspaceSize=512m"

Ya da doğrudan jmeter.bat / jmeter script’ini düzenleyebilirsin. Büyük testlerde 8GB bile ayırdım, duruma göre değişiyor.

JMeter Temel Kavramları

GUI’yi açmadan önce kavramları anlamak lazım. JMeter’da her şey hiyerarşik bir yapıda çalışıyor.

Test Plan: Her şeyin üst kabı. Tüm bileşenler bunun altında toplanıyor.

Thread Group: Sanal kullanıcıları temsil eden grup. Kaç kullanıcı, ne kadar süre, ramp-up süresi gibi ayarlar burada.

Sampler: Asıl HTTP isteklerini, veritabanı sorgularını veya diğer protokol isteklerini gönderen bileşen.

Listener: Test sonuçlarını toplayan ve gösteren bileşen. GUI modunda kullanışlı ama production testlerinde listener sayısını minimize etmek gerekiyor, çünkü her listener bellek tüketiyor.

Config Element: Değişkenler, HTTP default ayarları gibi yapılandırma bileşenleri.

Timer: İstekler arasına gecikme eklemek için. Gerçek kullanıcı davranışını simüle etmek istiyorsan olmazsa olmaz.

Assertion: Yanıtın beklenen formatta gelip gelmediğini kontrol eden bileşen. Performans testi yaparken hataları gözden kaçırmamak için kritik.

İlk Test Planı: Komut Satırından JMX Dosyası

GUI ile test planı oluşturmak başlangıç için iyi ama CI/CD’de her zaman headless mod kullanıyoruz. Ben test planlarımı XML olarak yazıp versiyon kontrolüne alırım. İşte temel bir HTTP yük testi JMX yapısı:

<?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="API Yük Testi" enabled="true">
      <stringProp name="TestPlan.comments">E-ticaret API yük testi</stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments">
        <collectionProp name="Arguments.arguments">
          <elementProp name="BASE_URL" elementType="Argument">
            <stringProp name="Argument.name">BASE_URL</stringProp>
            <stringProp name="Argument.value">api.example.com</stringProp>
          </elementProp>
        </collectionProp>
      </elementProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Kullanici Grubu" enabled="true">
        <intProp name="ThreadGroup.num_threads">100</intProp>
        <intProp name="ThreadGroup.ramp_time">60</intProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
        <stringProp name="ThreadGroup.duration">300</stringProp>
        <stringProp name="ThreadGroup.delay">0</stringProp>
        <boolProp name="ThreadGroup.scheduler">true</boolProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController">
          <boolProp name="LoopController.continue_forever">true</boolProp>
          <intProp name="LoopController.loops">-1</intProp>
        </elementProp>
      </ThreadGroup>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

Bu JMX dosyasını elle yazmak yerine başlangıçta GUI’den oluşturup export etmek daha pratik. Sonra bunu template olarak kullanabilirsin.

Gerçek Dünya Senaryosu 1: REST API Yük Testi

Diyelim ki bir e-ticaret uygulamasının ürün listeleme ve sepete ekleme API’lerini test ediyoruz. Bu tür mixed workload senaryoları en sık karşılaştığım durum.

# Test planını non-GUI modda çalıştır
jmeter -n 
  -t /opt/tests/ecommerce-load-test.jmx 
  -l /opt/results/test-results.jtl 
  -e 
  -o /opt/results/html-report 
  -Jbase_url=api.ecommerce.example.com 
  -Jthreads=200 
  -Jramp_up=120 
  -Jduration=600

Parametreler:

  • -n: Non-GUI (headless) mod
  • -t: Test planı dosyası
  • -l: Sonuç log dosyası (JTL formatı)
  • -e: Test sonunda HTML rapor oluştur
  • -o: HTML rapor çıktı dizini
  • -J: Test planındaki değişkenleri override et

Bu parametre geçme yöntemi çok değerli. Aynı JMX dosyasını farklı ortamlar için kullanabiliyorsun, her ortam için ayrı dosya tutmak zorunda kalmıyorsun.

Gerçek Dünya Senaryosu 2: Authentication ile Test

Production’a yakın testlerde mutlaka authentication var. JWT veya session cookie yönetimi JMeter’da biraz kafa karıştırıcı olabiliyor, ama doğru yapılandırdıktan sonra gayet temiz çalışıyor.

# HTTP Header Manager için properties dosyası oluştur
cat > /opt/tests/auth-config.properties << 'EOF'
# Auth endpoint
auth.endpoint=/api/v1/auth/login
[email protected]
auth.password=SecureTestPass123

# API endpoints
product.list.endpoint=/api/v1/products
cart.add.endpoint=/api/v1/cart/items
order.create.endpoint=/api/v1/orders

# Thread configuration
thread.count=150
ramp.up.seconds=90
test.duration.seconds=480
EOF

JSON Extractor ile token’ı yakalamak için JMX’e şu elementi ekliyoruz:

<JSONPathExtractor guiclass="JSONPathExtractorGui" testclass="JSONPathExtractor" 
  testname="JWT Token Extractor" enabled="true">
  <stringProp name="JSONPathExtractor.referenceNames">jwt_token</stringProp>
  <stringProp name="JSONPathExtractor.jsonPathExprs">$.data.token</stringProp>
  <stringProp name="JSONPathExtractor.defaultValues">TOKEN_NOT_FOUND</stringProp>
</JSONPathExtractor>

Sonrasında diğer isteklerde ${jwt_token} değişkeniyle kullanabiliyorsun. Bu pattern’i bir kez oturtunca authentication gerektiren her API için işe yarıyor.

Gerçek Dünya Senaryosu 3: Veritabanı Bağlantı Testi

JMeter sadece HTTP test etmiyor. JDBC sampler’la doğrudan veritabanı performansını da ölçebilirsin. Bunu özellikle veritabanı migration’larından sonra kullanıyorum.

# JDBC driver'ı JMeter lib klasörüne koy
wget https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.1/postgresql-42.7.1.jar
cp postgresql-42.7.1.jar /opt/jmeter/lib/

# MySQL için
wget https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.3.0/mysql-connector-j-8.3.0.jar
cp mysql-connector-j-8.3.0.jar /opt/jmeter/lib/

# JMeter'ı yeniden başlat

JDBC Connection Configuration için gerekli ayarlar:

  • Database URL: jdbc:postgresql://localhost:5432/mydb
  • JDBC Driver class: org.postgresql.Driver
  • Username/Password: Veritabanı credentials

Distributed Load Testing Kurulumu

Tek bir makineden 500+ concurrent user simüle etmek hem JMeter’ı hem de o makineyi yoruyor. Distributed mod kurarak birden fazla agent üzerinden yük dağıtabiliyoruz.

# Controller (Master) makinede
# jmeter.properties dosyasını düzenle
vi /opt/jmeter/bin/jmeter.properties

# Şu satırı bul ve agent IP'lerini ekle:
# remote_hosts=192.168.1.101,192.168.1.102,192.168.1.103

# Agent (Slave) makinelerde jmeter-server başlat
/opt/jmeter/bin/jmeter-server &

# Firewall ayarları (agent makinelerde)
sudo firewall-cmd --add-port=1099/tcp --permanent
sudo firewall-cmd --add-port=4000/tcp --permanent
sudo firewall-cmd --reload

# Master'dan distributed test başlat
jmeter -n 
  -t /opt/tests/distributed-test.jmx 
  -l /opt/results/distributed-results.jtl 
  -r 
  -e 
  -o /opt/results/distributed-report

-r parametresi remote agent’larda testi başlatıyor. Test bittikten sonra sonuçları otomatik olarak master’a topluyor.

CI/CD Pipeline Entegrasyonu

JMeter testlerini Jenkins veya GitLab CI’a entegre etmek standart bir pratik haline geldi. İşte minimal ama işlevsel bir GitLab CI yapılandırması:

# .gitlab-ci.yml
stages:
  - build
  - deploy
  - load-test
  - report

load-test:
  stage: load-test
  image: openjdk:17-slim
  before_script:
    - apt-get update && apt-get install -y wget
    - wget -q https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz
    - tar -xzf apache-jmeter-5.6.3.tgz
    - export JMETER_HOME=$(pwd)/apache-jmeter-5.6.3
    - export PATH=$JMETER_HOME/bin:$PATH
  script:
    - mkdir -p results/html-report
    - jmeter -n
        -t tests/load/api-test.jmx
        -l results/test-results.jtl
        -e
        -o results/html-report
        -Jbase_url=$STAGING_API_URL
        -Jthreads=50
        -Jramp_up=30
        -Jduration=120
    - |
      # Hata oranını kontrol et
      ERROR_RATE=$(grep -c "false" results/test-results.jtl || true)
      TOTAL=$(wc -l < results/test-results.jtl)
      echo "Toplam istek: $TOTAL, Hatalı: $ERROR_RATE"
      if [ "$ERROR_RATE" -gt "10" ]; then
        echo "Hata oranı çok yüksek, pipeline durduruluyor!"
        exit 1
      fi
  artifacts:
    when: always
    paths:
      - results/
    expire_in: 7 days
  only:
    - staging
    - main

Bu pipeline staging’e her deploy’da otomatik yük testi çalıştırıyor. Hata oranı 10’u geçerse pipeline başarısız sayılıyor. Threshold’u uygulamanın toleransına göre ayarlamak gerekiyor.

Sonuç Analizi ve Raporlama

Test bitti, elimizde JTL dosyası var. Bunu anlamlı hale getirmek için birkaç yöntem kullanıyorum.

# Mevcut JTL'den HTML rapor oluştur (test sonradan da yapılabilir)
jmeter -g /opt/results/test-results.jtl 
       -o /opt/results/final-report

# JTL dosyasından temel metrikleri çıkar
# Ortalama response time
awk -F',' 'NR>1 {sum+=$2; count++} END {printf "Ortalama: %.2f msn", sum/count}' results.jtl

# Hata oranı hesapla
awk -F',' 'NR>1 {total++; if($8=="false") errors++} END {printf "Hata Orani: %.2f%%n", (errors/total)*100}' results.jtl

# Percentile hesaplamak için sort kullan
awk -F',' 'NR>1 {print $2}' results.jtl | sort -n | awk '{all[NR]=$1} END {print "P95:", all[int(NR*0.95)], "ms"}'

Bu ham komutlar bazen rapordan daha hızlı bir fikir veriyor. Özellikle büyük JTL dosyalarında HTML rapor oluşturmak dakikalar alabilir.

Grafana ile JMeter Entegrasyonu

Production senaryolarında test sırasında canlı metrikleri izlemek istiyorsan InfluxDB + Grafana kombinasyonu çok iyi çalışıyor.

# jmeter.properties dosyasına ekle
backend_listener_classname=kg.apc.jmeter.visualizers.influxdb.InfluxdbBackendListenerClient

# Alternatif olarak JMX'e Backend Listener ekle
# InfluxDB URL: http://localhost:8086/write?db=jmeter
# Application: my-app-name
# Measurement: jmeter

# InfluxDB'ye yazım testi
curl -i -XPOST 'http://localhost:8086/write?db=jmeter' 
  --data-binary 'jmeter,transaction=HTTP,status=ok avg=125,min=45,max=890,pct90=340'

Grafana’da JMeter dashboard’u için community’nin hazırladığı dashboard ID 5496 oldukça kullanışlı. Import edip InfluxDB’yi bağlayınca neredeyse sıfır konfigürasyonla çalışıyor.

Sık Yapılan Hatalar ve Dikkat Edilmesi Gerekenler

Yıllar içinde gördüğüm en yaygın hatalar:

GUI modda büyük test çalıştırmak: JMeter GUI çok kaynak tüketiyor. 50 user üzerindeki testlerde mutlaka non-GUI mod kullan. GUI yalnızca test geliştirme aşamasında kullan.

Listener şişirmesi: Her Listener hafıza tüketiyor. Prodüksiyon testlerinde sadece “Simple Data Writer” kullan, “View Results Tree” gibi listener’ları devre dışı bırak.

Think time eksikliği: Gerçek kullanıcılar her isteği milisaniye arayla göndermez. Constant Timer veya Gaussian Random Timer ekleyerek gerçekçi bekleme süreleri tanımla. Ben genellikle 1-3 saniye arasında bir Gaussian timer kullanırım.

Test verisi tekrarı: Aynı kullanıcı adı ve şifreyle yüzlerce thread login olmaya çalışırsa senaryo gerçekçi değil. CSV Data Set Config ile gerçekçi test verisi kullan.

Ağ bant genişliğini hesaba katmamak: JMeter’ın çalıştığı makine ile test ettiğin sistem aynı ağdaysa sonuçlar yanıltıcı olabilir. Mümkünse JMeter agent’larını farklı bir network segment’ine veya cloud’a koy.

Sonuç

JMeter öğrenmesi biraz zaman alan ama bir kez oturtunca vazgeçilmez bir araç. k6 ve Locust kod tabanlı testler için belki daha modern hissettiriyor, ama JMeter’ın GUI’si ve geniş plugin ekosistemi özellikle ekip içinde test planı paylaşımını kolaylaştırıyor.

Başlangıç için önerdiğim yol: önce basit bir HTTP testi yaz, GUI’de çalıştır, sonuçları anla. Sonra aynı testi non-GUI modda çalıştır ve CI/CD’ye entegre et. Distributed testi ve Grafana entegrasyonunu olgunluk aşamasında ekle.

En önemli kural: Yük testini production crash’inden sonra değil, önce yap. Bir kere o 03:00 telefon ziliyle uyanıyorsun, bir daha uyanmak istemiyorsun. JMeter tam da bu yüzden var.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir