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:
abbu protokolü desteklemiyor - Dinamik parametreler: Her istekte farklı veri göndermek için
abyetersiz 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.