Apache ab ile Yük Testi ve Performans Ölçümü

Bir web uygulaması geliştirdiniz, staging ortamında her şey mükemmel görünüyor, production’a aldınız ve trafik gelmeye başladığında sistem çöküyor. Bu senaryo ne yazık ki çok tanıdık. İşte bu yüzden yük testi, production öncesi sürecin vazgeçilmez bir parçası olmalı. Apache’nin birlikte gelen ab (Apache Benchmark) aracı, basit ama güçlü bir yük testi çözümü sunuyor. Kurulum gerektirmiyor, her yerde mevcut ve sonuçları yorumlamak oldukça kolay. Bu yazıda ab aracını gerçek dünya senaryolarıyla birlikte derinlemesine inceleyeceğiz.

Apache ab Nedir ve Neden Kullanmalıyız?

ab, Apache HTTP Server projesiyle birlikte gelen komut satırı tabanlı bir HTTP yük testi aracıdır. Tam adı “Apache HTTP server benchmarking tool” olan bu araç, bir web sunucusuna belirli sayıda istek göndererek performans metrikleri toplar.

ab kullanmanın avantajları şunlardır:

  • Kurulum kolaylığı: Apache paketi yüklüyse zaten elinizin altında
  • Sıfır bağımlılık: Python, Node veya başka bir runtime gerektirmez
  • Hızlı sonuç: 30 saniyede anlamlı metrikler elde edersiniz
  • Scriptlenebilirlik: CI/CD pipeline’larına kolayca entegre edilebilir
  • Düşük kaynak kullanımı: Test makinesinde minimal overhead

Tabii ab‘nin sınırlamaları da var. Çok sayfalı senaryo testleri yapamıyor, JavaScript çalıştırmıyor ve gerçek kullanıcı davranışını simüle etmekte yetersiz kalabiliyor. Ancak bir endpoint’in ne kadar yük kaldırabileceğini ölçmek için mükemmel bir araç.

Kurulum

Çoğu sistemde ab zaten yüklü gelir. Değilse şu şekilde kurabilirsiniz:

# Ubuntu/Debian
sudo apt-get install apache2-utils

# CentOS/RHEL/Rocky Linux
sudo yum install httpd-tools

# macOS (Homebrew)
brew install httpd

# Kurulumu doğrula
ab -V

apache2-utils paketi, Apache web sunucusunun kendisini kurmadan sadece ab ve diğer yardımcı araçları yüklemenizi sağlar. Production sunucusuna Apache kurmak istemiyorsanız bu paket tam ihtiyacınıza göre.

Temel Kullanım ve Parametreler

ab‘nin sözdizimi oldukça basit:

ab [seçenekler] [http[s]://]hostname[:port]/path

En sık kullanılan parametreler şunlardır:

  • -n: Toplam gönderilecek istek sayısı
  • -c: Eş zamanlı (concurrent) bağlantı sayısı
  • -t: Test süresi saniye cinsinden (n yerine kullanılabilir)
  • -k: HTTP KeepAlive aktif eder
  • -H: Özel HTTP başlığı ekler
  • -C: Cookie ekler
  • -p: POST verisi içeren dosya yolu
  • -T: Content-Type başlığı (POST için)
  • -A: HTTP Authentication bilgisi (kullanıcı:şifre)
  • -s: SSL/TLS timeout süresi
  • -r: Socket hatalarında çıkış yapma, devam et
  • -v: Verbosity seviyesi (1-4 arası)
  • -g: Sonuçları gnuplot formatında dosyaya yaz
  • -e: Sonuçları CSV formatında dosyaya yaz
  • -l: Değişken boyutlu yanıtlar için hata verme

İlk testimizi yapalım:

# 1000 istek, 10 eş zamanlı bağlantı
ab -n 1000 -c 10 http://localhost/

Çıktıyı Anlamak

ab çalıştırdığınızda karşınıza çıkan raporu doğru okumak kritik önem taşıyor:

ab -n 5000 -c 50 http://yourdomain.com/

# Örnek çıktı:
# Server Software:        Apache/2.4.41
# Server Hostname:        yourdomain.com
# Server Port:            80
# Document Path:          /
# Document Length:        45231 bytes
# Concurrency Level:      50
# Time taken for tests:   12.453 seconds
# Complete requests:      5000
# Failed requests:        0
# Total transferred:      226640000 bytes
# HTML transferred:       226155000 bytes
# Requests per second:    401.52 [#/sec] (mean)
# Time per request:       124.530 [ms] (mean)
# Time per request:       2.491 [ms] (mean, across all concurrent requests)
# Transfer rate:          17771.23 [Kbytes/sec] received
#
# Percentage of the requests served within a certain time (ms)
#  50%     98
#  66%    112
#  75%    125
#  80%    134
#  90%    167
#  95%    198
#  98%    245
#  99%    289
# 100%    891 (longest request)

Bu çıktıdaki kritik metrikler:

  • Requests per second: Sunucunuzun saniyede kaç isteği karşıladığı. Bu değer ne kadar yüksekse o kadar iyi.
  • Time per request (mean): Bir isteğin ortalama tamamlanma süresi. Kullanıcı perspektifinden bu değer önemli.
  • Failed requests: Başarısız istek sayısı. Yük altında bu değerin sıfır olması hedef.
  • Percentile dağılımı: Özellikle 95. ve 99. yüzdelik dilimler, kötü deneyim yaşayan kullanıcı oranını gösterir. 99. yüzdelik dilim 891ms ise kullanıcıların %1’i neredeyse bir saniye bekliyor demektir.

Gerçek Dünya Senaryosu 1: Statik Site Testi

Önce en basit senaryoyla başlayalım. Nginx veya Apache ile servis edilen statik bir site:

# Baseline test - düşük yük
ab -n 1000 -c 10 -k http://static.yourdomain.com/

# Orta yük testi
ab -n 5000 -c 100 -k http://static.yourdomain.com/

# Stres testi - sistemin kırılma noktasını bulmak için
ab -n 10000 -c 500 -k http://static.yourdomain.com/

-k parametresi KeepAlive bağlantıları etkinleştirir. Gerçek tarayıcılar da bunu yaptığından testlerinizin gerçeğe daha yakın olması için bu parametreyi kullanın. Fark oldukça büyük olabilir; bazı durumlarda KeepAlive ile performans 3-4 kat artabilir.

Gerçek Dünya Senaryosu 2: REST API Endpoint Testi

Modern web uygulamalarında en kritik nokta genellikle API endpointleri. GET istekleri için:

# API endpoint GET testi
ab -n 2000 -c 50 
   -H "Accept: application/json" 
   -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." 
   http://api.yourdomain.com/v1/users

POST isteği göndermek için önce veri dosyası oluşturmanız gerekiyor:

# POST verisi dosyası oluştur
cat > post_data.json << 'EOF'
{
  "username": "testuser",
  "email": "[email protected]",
  "action": "search",
  "query": "performance"
}
EOF

# POST isteği ile yük testi
ab -n 1000 -c 20 
   -p post_data.json 
   -T "application/json" 
   -H "Authorization: Bearer your_token_here" 
   http://api.yourdomain.com/v1/search

Form verisi göndermek için:

# Form data ile POST
echo "username=admin&password=test123&remember=1" > form_data.txt

ab -n 500 -c 25 
   -p form_data.txt 
   -T "application/x-www-form-urlencoded" 
   -C "session_id=abc123xyz" 
   http://yourdomain.com/login

Gerçek Dünya Senaryosu 3: HTTPS Endpoint Testi

SSL/TLS overhead’ini ölçmek, performans optimizasyonu açısından önemli veriler sağlar:

# HTTPS testi - SSL handshake dahil
ab -n 2000 -c 50 -k https://secure.yourdomain.com/api/products

# SSL timeout süresini artır (yavaş bağlantılar için)
ab -n 2000 -c 50 -s 60 https://secure.yourdomain.com/api/products

HTTP ve HTTPS sonuçlarını karşılaştırdığınızda SSL overhead’ini görebilirsiniz. Modern sunucularda bu fark genellikle %5-15 arasında olsa da eski donanımlarda veya zayıf SSL konfigürasyonlarında %50’ye kadar çıkabilir. Bu noktada SSL session caching ve HTTP/2 devreye giriyor.

Bash Script ile Otomatik Yük Testi

Tek seferlik komut çalıştırmak yerine kapsamlı bir test senaryosu scripti yazmak çok daha profesyonel sonuçlar verir:

#!/bin/bash
# loadtest.sh - Kapsamlı yük testi scripti

TARGET_URL="${1:-http://localhost/}"
RESULTS_DIR="./ab_results_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$RESULTS_DIR"

echo "=========================================="
echo "Yük Testi Başlıyor: $TARGET_URL"
echo "Sonuçlar: $RESULTS_DIR"
echo "=========================================="

# Test seviyeleri: [istek_sayisi, eş_zamanlı_bağlantı]
declare -a TESTS=(
    "500:10"
    "1000:25"
    "2000:50"
    "5000:100"
    "10000:200"
)

for test in "${TESTS[@]}"; do
    REQUESTS=$(echo $test | cut -d: -f1)
    CONCURRENCY=$(echo $test | cut -d: -f2)
    
    echo ""
    echo "Test: $REQUESTS istek, $CONCURRENCY eş zamanlı bağlantı"
    echo "-------------------------------------------"
    
    OUTPUT_FILE="$RESULTS_DIR/test_r${REQUESTS}_c${CONCURRENCY}"
    
    ab -n "$REQUESTS" 
       -c "$CONCURRENCY" 
       -k 
       -r 
       -e "${OUTPUT_FILE}.csv" 
       -g "${OUTPUT_FILE}.gnuplot" 
       "$TARGET_URL" > "${OUTPUT_FILE}.txt" 2>&1
    
    # Özet metrikleri çıkar
    RPS=$(grep "Requests per second" "${OUTPUT_FILE}.txt" | awk '{print $4}')
    P95=$(grep "95%" "${OUTPUT_FILE}.txt" | awk '{print $2}')
    FAILED=$(grep "Failed requests" "${OUTPUT_FILE}.txt" | awk '{print $3}')
    
    echo "RPS: $RPS | P95 latency: ${P95}ms | Başarısız: $FAILED"
    
    # Başarısız istek eşiği
    if [ "$FAILED" -gt "0" ]; then
        echo "UYARI: $FAILED başarısız istek tespit edildi!"
    fi
    
    # Sistemin toparlanması için bekle
    sleep 5
done

echo ""
echo "=========================================="
echo "Tüm testler tamamlandı. Sonuçlar: $RESULTS_DIR"
echo "=========================================="

Bu scripti şu şekilde kullanabilirsiniz:

chmod +x loadtest.sh
./loadtest.sh http://yourdomain.com/api/products

Sonuçları Analiz Etmek

ab‘nin CSV çıktısını analiz etmek için basit bir Python scripti işinizi kolaylaştırır:

# CSV sonuçlarını görüntüle
# ab -e output.csv ile oluşturulan dosyayı işle

python3 << 'EOF'
import csv
import sys

csv_file = "test_r5000_c100.csv"

with open(csv_file, 'r') as f:
    reader = csv.reader(f)
    next(reader)  # başlığı atla
    data = list(reader)

percentiles = [50, 75, 90, 95, 99, 100]
print(f"{'Yüzdelik Dilim':<20} {'Süre (ms)':<15}")
print("-" * 35)

for row in data:
    pct = int(row[0])
    if pct in percentiles:
        ms = row[1]
        bar = "#" * (int(float(ms)) // 10)
        print(f"  {pct:>3}%{'':<15} {ms:<15} ms  {bar}")
EOF

Karşılaştırmalı Test: Farklı Konfigürasyonları Test Etme

ab‘nin en güçlü kullanım alanlarından biri, konfigürasyon değişikliklerinin etkisini ölçmek. Örneğin Apache’de MPM değiştirdiğinizde veya PHP-FPM pool ayarlarını düzenlediğinizde:

#!/bin/bash
# compare_configs.sh

echo "=== Konfigürasyon Karşılaştırma Testi ==="

# Test 1: Mevcut konfigürasyon
echo "Test 1: Prefork MPM"
RESULT1=$(ab -n 3000 -c 100 -k http://localhost/ 2>&1 | grep "Requests per second" | awk '{print $4}')
echo "RPS: $RESULT1"

echo ""
echo "MPM'i Event'e geçirip Apache'yi yeniden başlatın, ardından Enter'a basın..."
read

# Test 2: Yeni konfigürasyon
echo "Test 2: Event MPM"
RESULT2=$(ab -n 3000 -c 100 -k http://localhost/ 2>&1 | grep "Requests per second" | awk '{print $4}')
echo "RPS: $RESULT2"

echo ""
echo "Sonuç: Prefork $RESULT1 RPS vs Event $RESULT2 RPS"

# İyileşme yüzdesi
IMPROVEMENT=$(echo "scale=2; ($RESULT2 - $RESULT1) / $RESULT1 * 100" | bc)
echo "Değişim: %$IMPROVEMENT"

Yaygın Sorunlar ve Çözümleri

“apr_socket_recv: Connection reset by peer” Hatası

Bu hata genellikle sunucunun yükü kaldıramaması veya firewall’un bağlantıları kesmesi nedeniyle oluşur:

# -r parametresi ile socket hatalarında devam et
ab -n 5000 -c 100 -r http://yourdomain.com/

# Concurrency seviyesini düşür
ab -n 5000 -c 50 -r http://yourdomain.com/

“Too many open files” Hatası

Yüksek concurrency testlerinde file descriptor limitlerine çarpabilirsiniz:

# Mevcut limiti kontrol et
ulimit -n

# Geçici olarak artır (root veya sudo gerektirebilir)
ulimit -n 65536

# Kalıcı değişiklik için /etc/security/limits.conf
echo "* soft nofile 65536" | sudo tee -a /etc/security/limits.conf
echo "* hard nofile 65536" | sudo tee -a /etc/security/limits.conf

Yanlış Sunucu Ölçümü Sorunu

Test makinesinin kendisi bottleneck haline gelebilir. Bunu kontrol edin:

# Test sırasında sistem kaynaklarını izle
# Ayrı bir terminal'de:
watch -n 1 "vmstat 1 1 && ss -s"

# Test makinesindeki CPU kullanımını takip et
ab -n 10000 -c 200 http://target-server.com/ &
AB_PID=$!
while kill -0 $AB_PID 2>/dev/null; do
    echo -n "Test makinesi CPU: "
    top -bn1 | grep "Cpu(s)" | awk '{print $2}' 
    sleep 2
done

Eğer test makinenizin CPU’su %80’in üzerine çıkıyorsa, sonuçlarınız güvenilir değil demektir. Bu durumda birden fazla makineden eş zamanlı test çalıştırmayı düşünün.

Gerçek Dünya Senaryosu 4: CI/CD Pipeline Entegrasyonu

Performans regresyonlarını otomatik yakalamak için ab‘yi deployment pipeline’ınıza entegre edebilirsiniz:

#!/bin/bash
# performance_gate.sh - Deployment sonrası performans kontrolü

set -e

TARGET_URL="${TARGET_URL:-http://staging.yourdomain.com/}"
MIN_RPS="${MIN_RPS:-200}"
MAX_P95_MS="${MAX_P95_MS:-500}"

echo "Performans kapısı kontrolü başlıyor..."
echo "Hedef: $TARGET_URL"
echo "Minimum RPS: $MIN_RPS"
echo "Maksimum P95 latency: ${MAX_P95_MS}ms"

# Warm-up
echo "Sunucu ısınıyor..."
ab -n 100 -c 10 -q "$TARGET_URL" > /dev/null 2>&1
sleep 3

# Asıl test
RESULTS=$(ab -n 2000 -c 50 -k -r "$TARGET_URL" 2>&1)

RPS=$(echo "$RESULTS" | grep "Requests per second" | awk '{print $4}' | cut -d. -f1)
P95=$(echo "$RESULTS" | grep "95%" | awk '{print $2}')
FAILED=$(echo "$RESULTS" | grep "Failed requests" | awk '{print $3}')

echo ""
echo "Sonuçlar:"
echo "  RPS: $RPS (minimum: $MIN_RPS)"
echo "  P95 Latency: ${P95}ms (maksimum: ${MAX_P95_MS}ms)"
echo "  Başarısız İstek: $FAILED"

# Kontroller
PASSED=true

if [ "$FAILED" -gt "0" ]; then
    echo "HATA: Başarısız istek tespit edildi: $FAILED"
    PASSED=false
fi

if [ "$RPS" -lt "$MIN_RPS" ]; then
    echo "HATA: RPS çok düşük. Beklenen: >$MIN_RPS, Gerçek: $RPS"
    PASSED=false
fi

if [ "$P95" -gt "$MAX_P95_MS" ]; then
    echo "HATA: P95 latency çok yüksek. Beklenen: <${MAX_P95_MS}ms, Gerçek: ${P95}ms"
    PASSED=false
fi

if $PASSED; then
    echo ""
    echo "BAŞARILI: Tüm performans kriterleri karşılandı."
    exit 0
else
    echo ""
    echo "BAŞARISIZ: Deployment durduruldu, performans kriterleri karşılanmadı."
    exit 1
fi

Bu scripti Jenkins, GitLab CI veya GitHub Actions’a şu şekilde entegre edebilirsiniz:

# .gitlab-ci.yml veya Jenkinsfile içinde
# Staging'e deploy sonrası çalıştır
TARGET_URL="http://staging.example.com/" MIN_RPS=150 MAX_P95_MS=800 ./performance_gate.sh

ab’nin Sınırlarını Bilmek

ab güçlü ama her test senaryosu için yeterli değil. Şu durumlarda başka araçlara geçmenizi öneririm:

  • Çok adımlı senaryolar (login > sepete ekle > ödeme): k6 veya Locust kullanın
  • Gerçekçi kullanıcı davranışı simülasyonu: Gatling veya JMeter tercih edin
  • Coğrafi dağıtımlı testler: BlazeMeter veya k6 Cloud daha uygun
  • WebSocket testleri: ab bu protokolü desteklemiyor
  • Dinamik parametreler: Her istekte farklı veri göndermek için ab yetersiz kalır

İyi Bir Yük Testi Metodolojisi

Test araçları kadar, testi nasıl yaptığınız da önemli:

  • Warm-up ile başlayın: Sunucu cache’ini doldurmak için önce düşük yükle 1-2 dakika çalıştırın
  • Kademeli artış yapın: Concurrency’i birdenbire 500’e çıkarmak yerine 10, 25, 50, 100, 200 şeklinde artırın
  • Aynı testi birden fazla çalıştırın: Tek bir sonuca güvenmeyin, 3 kez çalıştırıp ortalamasını alın
  • Sistem metriklerini eş zamanlı izleyin: top, iostat, netstat çıktılarını kaydedin
  • Üretim trafiğini simüle edin: Test ettiğiniz endpoint gerçekte ne kadar kullanılıyor? Ona göre test edin
  • Log’ları inceleyin: Test sırasında Apache error log’unda neler oluyor? tail -f /var/log/apache2/error.log

Sonuç

Apache ab, sysadmin ve geliştirici araç kutusunda mutlaka bulunması gereken, öğrenmesi beş dakika süren ama derinlemesine kullanıldığında çok değerli veriler sağlayan bir araç. Production’a çıkmadan önce temel endpoint’lerinizi test etmek, bir konfigürasyon değişikliğinin performansı nasıl etkilediğini anlamak veya deployment pipeline’ınıza bir performans kapısı eklemek için mükemmel bir başlangıç noktası.

Önemli olan sadece ab çalıştırıp rakamları görmek değil, o rakamları doğru yorumlamak ve aksiyon almak. RPS değeriniz düşükse hangi kaynak bottleneck oluşturuyor? P95 latency yüksekse veritabanı sorgusu mu, uygulama kodu mu, ağ gecikmesi mi? ab size problemi gösterir, sebebi bulmak sizin işiniz.

Son olarak şunu vurgulamak isterim: yük testini production üzerinde yapmayın. Mutlaka production’a mümkün olduğunca yakın bir staging ortamı kullanın. Yoksa “performans testi yapıyorum” derken gerçek kullanıcılarınızın deneyimini mahvedebilirsiniz.

Yorum yapın