Apache Bench (ab) ile Hızlı Web Sunucu Performans Testi
Bir sunucunun gerçekten ne kadar yük kaldırabileceğini öğrenmenin en hızlı yolu, ona yük bindirmektir. Kulağa kaba geliyor, biliyorum. Ama production’a çıkmadan önce bu testi yapmamak daha kaba bir hata olur. Apache Bench (ab) işte tam bu iş için var: kurulumu beş dakika, öğrenmesi on dakika, ama size vereceği bilgi saatler süren analizin yerini tutabilir.
Apache Bench Nedir ve Neden Hâlâ Kullanılır?
Apache HTTP Server projesinin bir parçası olarak gelen ab, aslında onlarca yıllık bir araç. k6, Locust, JMeter gibi modern alternatiflerin yanında “eski kafalı” görünebilir. Ama şunu söyleyeyim: bir sunucunun basit bir endpoint’e kaç isteği saniyede kaldırabileceğini test etmek için JMeter açmak, vida çakmak için elektrikli matkap kullanmak gibi bir şeydir. ab ise tam bu iş için biçilmiş kaftan.
Gerçek dünyada ab‘yi şu senaryolarda kullanıyorum:
- Yeni bir Nginx konfigürasyonu değişikliğinden sonra hızlı bir “before/after” karşılaştırması
- Bir API endpoint’inin kabaca kaç RPS (requests per second) kaldırdığını anlamak
- Bir deployment pipeline’ında smoke test olarak çalıştırmak
- SSL/TLS konfigürasyonunun performansa etkisini ölçmek
Daha karmaşık senaryolar için evet, Locust veya k6’ya geçiyorum. Ama ab hızlı ve işe yarıyor. Sisteminizde muhtemelen zaten kurulu bile.
Kurulum
Çoğu Linux dağıtımında ab, apache2-utils veya httpd-tools paketi içinde gelir.
# Ubuntu/Debian
sudo apt-get install apache2-utils
# CentOS/RHEL/Rocky Linux
sudo dnf install httpd-tools
# macOS (Homebrew)
brew install httpd
# Kurulumu doğrula
ab -V
Windows’ta ise Apache HTTP Server’ın binary paketini indirip bin/ klasöründen ab.exe‘yi kullanabilirsiniz. Ama dürüst olalım, bu tür testleri Windows’tan yapıyorsanız büyük ihtimalle bir şeyler yanlış gidiyor.
Temel Kullanım ve Parametreler
ab‘nin sözdizimi son derece basit:
ab [seçenekler] [http://]sunucu[:port]/path
URL’nin sonundaki / işaretine dikkat edin. Bunu unutmak en sık yapılan hatalardan biridir ve ab: invalid URL hatasıyla karşılaşırsınız.
En sık kullandığım parametreler şöyle:
- -n: Toplam gönderilecek istek sayısı
- -c: Eş zamanlı bağlantı (concurrency) sayısı
- -t: Test süresi saniye cinsinden (n yerine kullanılabilir)
- -k: HTTP KeepAlive aktif eder
- -H: Özel header ekler
- -p: POST isteği için body dosyası
- -T: Content-Type header’ı (POST ile birlikte kullanılır)
- -A: HTTP Basic Authentication (kullanıcı:şifre)
- -C: Cookie gönderir
- -s: SSL/TLS timeout süresi
- -e: Sonuçları CSV olarak kaydeder
- -g: Sonuçları gnuplot formatında kaydeder
- -r: Socket hataları olduğunda testi durdurmaz
- -v: Verbosity seviyesi (1-4 arası)
İlk temel testimizi çalıştıralım:
ab -n 1000 -c 10 http://localhost/
Bu komut localhost’a 10 eş zamanlı bağlantıyla toplamda 1000 istek gönderir. Sonuç çıktısına biraz sonra bakacağız.
Çıktıyı Okumak: Sayılar Ne Anlama Geliyor?
ab‘nin en güçlü yanlarından biri okunabilir bir çıktı üretmesidir. Bir örnek çıktı görelim:
ab -n 5000 -c 50 -k http://example.com/api/health
Çıktı şuna benzer bir şey üretir:
Server Software: nginx/1.24.0
Server Hostname: example.com
Server Port: 80
Concurrency Level: 50
Time taken for tests: 4.823 seconds
Complete requests: 5000
Failed requests: 0
Keep-Alive requests: 4950
Total transferred: 2150000 bytes
HTML transferred: 750000 bytes
Requests per second: 1036.67 [#/sec] (mean)
Time per request: 48.227 [ms] (mean)
Time per request: 0.965 [ms] (mean, across all concurrent requests)
Transfer rate: 435.21 [Kbytes/sec] received
Percentage of the requests served within a certain time (ms)
50% 45
66% 48
75% 51
80% 53
90% 61
95% 72
98% 89
99% 102
100% 187 (longest request)
Burada dikkat etmeniz gereken değerler:
- Requests per second: Sunucunuzun saniyede kaç isteği karşılayabildiği. Bu değer ne kadar yüksekse o kadar iyi.
- Time per request (mean): Ortalama yanıt süresi. Ama bu değere tek başına güvenmeyin.
- Failed requests: Sıfır olmalı. Sıfırdan büyükse ciddi bir sorun var demektir.
- Percentile dağılımı: Bence çıktının en değerli kısmı burası. 99. persentil (p99) değeriniz 500ms’yi geçiyorsa, kullanıcılarınızın yüzde biri her zaman bu yavaşlığı yaşıyor demektir.
p99 ile ortalama arasındaki farka bakın. Bu fark büyükse, sunucunuzda tutarsız yanıt süreleri var demektir. Belki belirli istekler veritabanında lock’a takılıyor, belki garbage collection devreye giriyor, belki bir connection pool dolup taşıyor. Bu fark bir alarm işareti.
Gerçek Dünya Senaryoları
Senaryo 1: Nginx Konfigürasyon Değişikliği Öncesi/Sonrası
Diyelim ki worker_processes ve worker_connections değerlerini artırdınız. Etkisini ölçmek için:
# Değişiklik öncesi - sonuçları kaydet
ab -n 10000 -c 100 -k -e oncesi.csv http://localhost/
# nginx.conf değişikliklerini uygula
sudo nginx -s reload
# Değişiklik sonrası
ab -n 10000 -c 100 -k -e sonrasi.csv http://localhost/
CSV dosyalarını karşılaştırarak tam percentile dağılımını görebilirsiniz. Ben bu karşılaştırmayı genellikle basit bir awk komutuyla yapıyorum:
# İki CSV'nin 95. persentil değerlerini karşılaştır
awk -F',' 'NR==96{print "Öncesi p95:", $2}' oncesi.csv
awk -F',' 'NR==96{print "Sonrası p95:", $2}' sonrasi.csv
Senaryo 2: POST İstekleriyle API Testi
Çoğu API testi GET değil POST gerektirir. ab bunu da destekler, sadece biraz daha konfigürasyon gerekir:
# Önce POST body'sini bir dosyaya yaz
cat > post_data.json << 'EOF'
{
"username": "testuser",
"action": "login",
"timestamp": 1699900000
}
EOF
# POST isteği gönder
ab -n 2000 -c 20
-p post_data.json
-T "application/json"
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.test"
http://localhost:8080/api/v1/login
Burada bir uyarı: ab POST body’sini her istekte aynı gönderir. Dinamik veri gerektiren testler için (benzersiz kullanıcı ID’leri, random payload’lar gibi) Locust veya k6’ya geçmek gerekir. ab‘nin bu konudaki sınırını bilmek, ne zaman başka araç kullanacağınızı anlamanıza yardımcı olur.
Senaryo 3: HTTPS Endpoint Testi
SSL/TLS overhead’ını ölçmek için:
# HTTP testi
ab -n 5000 -c 50 http://example.com/api/status
# HTTPS testi (aynı endpoint)
ab -n 5000 -c 50 https://example.com/api/status
İki test arasındaki fark size TLS handshake maliyetini gösterir. KeepAlive aktifken bu fark dramatik şekilde azalır, çünkü her istekte TLS yeniden kurulmaz:
ab -n 5000 -c 50 -k https://example.com/api/status
Senaryo 4: Cookie Gerektiren Oturum Testi
Bazı endpoint’ler oturum cookie’si gerektiriyor. Bunu aşmanın yolu:
# Önce tarayıcıdan veya curl ile oturum aç, cookie'yi al
curl -c cookies.txt -d "user=admin&pass=secret" http://localhost/login
# Cookie'yi ab'ye ver
ab -n 3000 -c 30
-C "session=abc123def456"
http://localhost/dashboard
Sistematik Yük Testi: Kırılma Noktasını Bulmak
Sunucunuzun gerçek kapasitesini anlamak için concurrency’i kademeli olarak artırın. Bu yaklaşıma genellikle “step load test” diyorum:
#!/bin/bash
# step_load_test.sh
# Sunucunun kırılma noktasını adım adım bulur
TARGET="http://localhost/"
REQUESTS=2000
echo "Concurrency, RPS, P95_ms, Failed" > load_results.csv
for CONCURRENCY in 1 5 10 25 50 100 200 500; do
echo "Test ediliyor: -c $CONCURRENCY"
RESULT=$(ab -n $REQUESTS -c $CONCURRENCY -q "$TARGET" 2>&1)
RPS=$(echo "$RESULT" | grep "Requests per second" | awk '{print $4}')
P95=$(echo "$RESULT" | grep "95%" | awk '{print $2}')
FAILED=$(echo "$RESULT" | grep "Failed requests" | awk '{print $3}')
echo "$CONCURRENCY, $RPS, $P95, $FAILED" >> load_results.csv
echo " RPS: $RPS | P95: ${P95}ms | Başarısız: $FAILED"
# Hata oranı artmaya başlarsa dur
if [ "$FAILED" -gt "10" ]; then
echo "Hata eşiği aşıldı, test durduruluyor."
break
fi
sleep 5 # Sunucunun toparlanması için bekle
done
echo ""
echo "Sonuçlar load_results.csv dosyasına kaydedildi."
Bu script’i çalıştırdığınızda RPS’nin hangi concurrency seviyesinde platoya ulaştığını veya düşmeye başladığını göreceksiniz. İşte o nokta sunucunuzun pratik kapasitesidir.
Sonuçları Görselleştirme: gnuplot ile Hızlı Grafik
ab, -g parametresiyle gnuplot formatında veri üretir. Eğer sisteminizde gnuplot varsa güzel grafikler çizebilirsiniz:
# gnuplot formatında veri kaydet
ab -n 5000 -c 50 -g test_sonuclari.gnuplot http://localhost/
# Basit bir latency grafiği çiz
gnuplot << 'EOF'
set terminal png size 1200,600
set output "latency_grafik.png"
set title "Request Latency Dağılımı"
set xlabel "İstek Sırası"
set ylabel "Yanıt Süresi (ms)"
set grid
plot "test_sonuclari.gnuplot" using 9 with lines title "Yanıt Süresi (ms)" lc rgb "steelblue"
EOF
Gnuplot tercih etmiyorsanız, -e ile üretilen CSV’yi Excel veya Google Sheets’e aktarıp percentile dağılımı grafiğini oradan çizebilirsiniz.
Yaygın Hatalar ve Çözümleri
Yıllar içinde ab kullanırken karşılaştığım tipik sorunlar:
“apr_socket_recv: Connection refused”: Test ettiğiniz servis çalışmıyor veya yanlış porta bağlanıyorsunuz. Kontrol edin:
ss -tlnp | grep :80
“apr_socket_connect(): Connection reset by peer”: Sunucu bağlantıları reddediyor. Büyük ihtimalle ulimit değerleri çok düşük. Hem test makinenizde hem de sunucuda kontrol edin:
ulimit -n 65536
Sahte yüksek performans sonuçları: Eğer ab‘yi ve web sunucusunu aynı makinede çalıştırıyorsanız, sonuçlar gerçekçi olmayabilir. Ağ gecikmesi yokken ölçülen performans, production koşullarını yansıtmaz. Test aracını ayrı bir makineden çalıştırın.
“SSL handshake failed”: Self-signed sertifika varsa veya sertifika doğrulamasını atlamak istiyorsanız, ab‘nin built-in bir seçeneği yok. Bu durumda HAProxy veya stunnel üzerinden yönlendirme yapabilir ya da doğrudan k6 gibi bir araca geçebilirsiniz.
ab’nin Sınırlarını Bilmek
ab güçlü ama sınırlı bir araç. Şu durumlarda başka araçlara geçmeniz gerekir:
- Birden fazla farklı URL’yi test etmek istiyorsanız (k6 veya Locust)
- Dinamik kullanıcı davranışı simüle etmek gerekiyorsa (Locust)
- Test sırasında gerçek zamanlı metrik görselleştirme istiyorsanız (Grafana + k6)
- Çok sayıda eş zamanlı kullanıcı gerekiyorsa ve tek makinenin kapasitesi yetmiyorsa (JMeter distributed mode)
- WebSocket veya gRPC test edecekseniz (k6)
Ben ab‘yi şöyle konumlandırıyorum: hızlı sağlık kontrolü ve basit karşılaştırmalar için birinci tercih, karmaşık senaryo testleri için ise sadece bir başlangıç noktası.
Production Öncesi Checklist
ab testi yapmadan önce bir kontrol listesi:
- Test ortamının production’a mümkün olduğunca yakın olduğundan emin olun. Farklı donanım, farklı sonuçlar verir.
- Test makinenizin kendi limitlerine takılmadığınızı doğrulayın.
ulimit -ndeğerini ve CPU kullanımını izleyin. - Testler sırasında sunucu metriklerini de izleyin:
vmstat 1,iostat -x 1,ss -skomutları yardımcı olur. - Cache’i test öncesinde durumuna karar verin. Warm cache testi mi, cold cache testi mi yapmak istiyorsunuz?
- Testleri iş saatleri dışında yapın. Eğer production sistemini test ediyorsanız, bu kritik.
- Baseline oluşturun. İlk test sonuçlarınızı kaydedin, sonraki değişiklikleri bununla karşılaştırın.
# Sunucu durumunu izlemek için ayrı bir terminalde
watch -n 1 "ss -s && echo '---' && uptime && echo '---' && free -h"
Sonuç
Apache Bench, Swiss Army Knife sysadmin araç setinin ayrılmaz bir parçası. Evet, Locust daha esnek, k6 daha modern, JMeter daha kapsamlı. Ama bunların hiçbiri ab‘nin sunduğu sadelik ve hıza sahip değil.
Bir sunucu değişikliğinin performansı etkileyip etkilemediğini beş dakikada anlamak istiyorsanız, ab -n 5000 -c 50 URL yazıp enter’a basın. Çıktıyı okuyun, percentile dağılımına bakın, failed requests sıfır mı kontrol edin, RPS değerini bir yere not edin.
Sonra değişikliği yapın. Testi tekrar çalıştırın. Karşılaştırın.
Bu kadar basit. Bu kadar güçlü. Production’da sürprizle karşılaşmak istemiyorsanız, ab sizin ilk savunma hattınız olsun.
