Wie viele Anfragen kann Ihr Webserver verarbeiten? Benchmarking-Tools wie Apache Bench, wrk und siege helfen, die Leistungsgrenzen zu finden und Optimierungen zu validieren.

Warum Benchmarking?

Anwendungsfälle:
- Maximale Kapazität ermitteln
- Optimierungen validieren
- Bottlenecks finden
- Server-Sizing planen
- Vor/Nach-Vergleiche

Apache Bench (ab)

Installation

# Debian/Ubuntu
apt install apache2-utils

# CentOS/RHEL
dnf install httpd-tools

Grundlegende Nutzung

# 1000 Anfragen, 10 gleichzeitig
ab -n 1000 -c 10 http://example.com/

# Mit Keep-Alive
ab -n 1000 -c 10 -k http://example.com/

# POST-Anfrage
ab -n 1000 -c 10 -p data.txt -T "application/json" http://example.com/api

Wichtige Parameter

| Parameter | Beschreibung | |-----------|--------------| | -n | Anzahl Anfragen | | -c | Gleichzeitige Verbindungen | | -k | Keep-Alive aktivieren | | -t | Zeitlimit in Sekunden | | -p | POST-Daten-Datei | | -T | Content-Type Header | | -H | Zusätzlicher Header |

Beispiel-Ausgabe

Server Software:        nginx/1.24.0
Server Hostname:        example.com
Server Port:            80

Document Path:          /
Document Length:        1256 bytes

Concurrency Level:      10
Time taken for tests:   5.234 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      1456000 bytes
HTML transferred:       1256000 bytes
Requests per second:    191.06 [#/sec] (mean)
Time per request:       52.340 [ms] (mean)
Time per request:       5.234 [ms] (mean, across all concurrent requests)
Transfer rate:          271.72 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    2   0.5      2       8
Processing:    10   50  15.3     48     120
Waiting:        8   48  15.0     46     118
Total:         12   52  15.4     50     122

Percentage of the requests served within a certain time (ms)
  50%     50
  66%     55
  75%     60
  80%     65
  90%     75
  95%     85
  99%    105
 100%    122 (longest request)

Wichtige Metriken

- Requests per second: Durchsatz
- Time per request: Latenz pro Anfrage
- Failed requests: Fehler
- Transfer rate: Bandbreite
- 50%/95%/99%: Perzentile (wichtig für SLAs)

wrk - Modernes HTTP-Benchmarking

Installation

# Debian/Ubuntu
apt install wrk

# Aus Source
git clone https://github.com/wg/wrk.git
cd wrk
make
cp wrk /usr/local/bin/

Grundlegende Nutzung

# 30 Sekunden, 12 Threads, 400 Verbindungen
wrk -t12 -c400 -d30s http://example.com/

Parameter

| Parameter | Beschreibung | |-----------|--------------| | -t | Anzahl Threads | | -c | Gleichzeitige Verbindungen | | -d | Testdauer | | -s | Lua-Skript | | --latency | Latenz-Statistiken |

Beispiel-Ausgabe

Running 30s test @ http://example.com/
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    25.32ms   15.67ms 245.89ms   74.23%
    Req/Sec     1.35k   234.56     2.45k    68.75%
  Latency Distribution
     50%   22.45ms
     75%   32.12ms
     90%   45.67ms
     99%   89.23ms
  485234 requests in 30.01s, 578.45MB read
Requests/sec:  16169.12
Transfer/sec:     19.28MB

POST-Anfragen mit Lua-Skript

-- post.lua
wrk.method = "POST"
wrk.body   = '{"username":"test","password":"test123"}'
wrk.headers["Content-Type"] = "application/json"
wrk -t4 -c100 -d30s -s post.lua http://example.com/api/login

Dynamische Requests

-- dynamic.lua
counter = 0

request = function()
   counter = counter + 1
   path = "/api/items/" .. counter
   return wrk.format("GET", path)
end

siege - Load Testing

Installation

# Debian/Ubuntu
apt install siege

# CentOS/RHEL
dnf install siege

Grundlegende Nutzung

# 50 Benutzer, 1 Minute
siege -c50 -t1M http://example.com/

# Bestimmte Anzahl Wiederholungen
siege -c50 -r10 http://example.com/

# Mit Delay zwischen Anfragen
siege -c50 -t1M -d5 http://example.com/

Parameter

| Parameter | Beschreibung | |-----------|--------------| | -c | Gleichzeitige Benutzer | | -t | Testdauer (S/M/H) | | -r | Wiederholungen pro User | | -d | Delay zwischen Anfragen | | -f | URL-Datei | | -i | Internet-Modus (zufällige URLs) | | -b | Benchmark-Modus (kein Delay) |

Beispiel-Ausgabe

Transactions:                  12345 hits
Availability:                  99.95 %
Elapsed time:                  59.98 secs
Data transferred:              45.67 MB
Response time:                 0.24 secs
Transaction rate:              205.81 trans/sec
Throughput:                    0.76 MB/sec
Concurrency:                   49.23
Successful transactions:       12345
Failed transactions:           6
Longest transaction:           2.34
Shortest transaction:          0.01

URL-Liste testen

# urls.txt
http://example.com/
http://example.com/about
http://example.com/products
http://example.com/contact
siege -c50 -t1M -i -f urls.txt

Konfiguration

# ~/.siege/siege.conf
verbose = false
color = on
quiet = false
benchmark = false

Vergleich der Tools

| Feature | ab | wrk | siege | |---------|-----|-----|-------| | Einfachheit | Sehr einfach | Mittel | Einfach | | Performance | Mittel | Sehr hoch | Mittel | | HTTP/2 | Nein | Nein | Nein | | Scripting | Nein | Lua | URLs | | Threads | Single | Multi | Multi | | Anwendung | Quick Tests | High Load | Real User |

Benchmarking Best Practices

Was zu beachten ist

1. Von externem Server testen
   - Nicht vom gleichen Server!
   - Netzwerk-Latenz einbeziehen

2. Warmlaufen lassen
   - Cache aufwärmen
   - Verbindungen etablieren

3. Mehrere Durchläufe
   - Konsistente Ergebnisse?
   - Varianz beachten

4. Realistische Szenarien
   - Verschiedene URLs
   - POST und GET mischen
   - Session-Handling

Test-Szenario entwickeln

#!/bin/bash
# benchmark.sh

URL="http://example.com"
WARMUP_TIME=10
TEST_TIME=60

echo "=== Warmup ==="
wrk -t2 -c50 -d${WARMUP_TIME}s $URL > /dev/null

echo "=== Test 1: Low Concurrency ==="
wrk -t4 -c100 -d${TEST_TIME}s --latency $URL

echo "=== Test 2: Medium Concurrency ==="
wrk -t8 -c500 -d${TEST_TIME}s --latency $URL

echo "=== Test 3: High Concurrency ==="
wrk -t12 -c1000 -d${TEST_TIME}s --latency $URL

Server-Monitoring während Test

# In separatem Terminal
watch -n 1 "top -bn1 | head -20"

# CPU und Memory
vmstat 1

# Netzwerk
iftop

# Nginx-Verbindungen
watch "ss -s"

Ergebnisse interpretieren

Durchsatz vs. Latenz

Ziel: Maximaler Durchsatz bei akzeptabler Latenz

Typische Muster:
- Linear: Durchsatz steigt mit Concurrency
- Sättigung: Durchsatz stagniert
- Kollaps: Latenz explodiert, Durchsatz sinkt

Bottleneck finden

CPU-Limit:
- CPU bei 100%
- Lösung: Mehr Worker, Caching

RAM-Limit:
- Swap-Nutzung steigt
- Lösung: Weniger Worker, mehr RAM

I/O-Limit:
- Hohe iowait
- Lösung: SSD, Caching

Netzwerk-Limit:
- Bandbreite ausgereizt
- Lösung: Compression, CDN

Beispiel-Analyse

Test 1: 100 Verbindungen → 5000 req/s, 20ms Latenz
Test 2: 500 Verbindungen → 8000 req/s, 60ms Latenz
Test 3: 1000 Verbindungen → 7500 req/s, 130ms Latenz

Interpretation:
- Maximum bei ca. 500 Verbindungen
- Ab 1000 beginnt Degradation
- Sweet Spot: 400-600 Verbindungen

Webserver-Tuning validieren

Vor/Nach-Vergleich

#!/bin/bash
# compare.sh

echo "=== VORHER ===" | tee results.txt
wrk -t8 -c400 -d30s --latency http://example.com/ | tee -a results.txt

echo ""
echo "Jetzt Optimierungen durchführen..."
read -p "Press Enter to continue..."

echo "" | tee -a results.txt
echo "=== NACHHER ===" | tee -a results.txt
wrk -t8 -c400 -d30s --latency http://example.com/ | tee -a results.txt

Typische Optimierungen

# Nginx Worker
worker_processes auto;
worker_connections 4096;

# PHP-FPM Pool
pm = dynamic
pm.max_children = 50
pm.start_servers = 10

# MySQL
innodb_buffer_pool_size = 1G

HTTP/2 Benchmarking

h2load (nghttp2)

# Installation
apt install nghttp2-client

# Benchmark
h2load -n10000 -c100 -m10 https://example.com/

Parameter

-n: Anzahl Anfragen
-c: Verbindungen
-m: Max Streams pro Verbindung

Automatisierte Benchmarks

Mit Cron

#!/bin/bash
# /usr/local/bin/daily-benchmark.sh

DATE=$(date +%Y-%m-%d)
RESULTS_DIR="/var/log/benchmarks"
URL="http://example.com/"

mkdir -p $RESULTS_DIR

wrk -t4 -c200 -d60s --latency $URL > "$RESULTS_DIR/wrk-$DATE.txt" 2>&1

Ergebnisse sammeln

#!/bin/bash
# Parse wrk results

for file in /var/log/benchmarks/wrk-*.txt; do
    date=$(basename $file | cut -d- -f2-4 | cut -d. -f1)
    rps=$(grep "Requests/sec" $file | awk '{print $2}')
    latency=$(grep "Latency" $file | head -1 | awk '{print $2}')
    echo "$date,$rps,$latency"
done

Zusammenfassung

| Tool | Anwendungsfall | |------|----------------| | ab | Schnelle Tests, einfache Anfragen | | wrk | High-Performance, Scripting | | siege | User-Simulation, URL-Listen | | h2load | HTTP/2 Testing |

Fazit

Webserver-Benchmarking hilft, Leistungsgrenzen zu verstehen und Optimierungen zu validieren. Verwenden Sie wrk für hohe Last, ab für schnelle Tests und siege für realistische Szenarien. Testen Sie immer von externen Systemen, führen Sie mehrere Durchläufe durch und beobachten Sie Server-Metriken während der Tests. Fokussieren Sie auf das 95. oder 99. Perzentil für realistische SLA-Bewertungen.