Sie haben einen Endpunkt ausgeliefert. Er liefert das richtige JSON in Postman zurück. Aber Sie haben keine Ahnung, was passiert, wenn 200 Clients gleichzeitig darauf zugreifen. Hält er 500 Anfragen pro Sekunde stand, oder bricht die Latenz bei 50 zusammen? ApacheBench beantwortet diese Frage mit einem einzigen Befehl.
ApacheBench, aufgerufen als ab, ist ein Befehlszeilentool, das eine feste Anzahl von HTTP-Anfragen an eine einzelne URL sendet und Durchsatz sowie Latenz meldet. Es wird mit dem Apache HTTP Server geliefert und existiert seit Jahrzehnten. Es ist klein, schnell auszuführen und gibt Ihnen einen schnellen Überblick darüber, wie viel Last ein Endpunkt bewältigen kann.
Dieser Leitfaden behandelt die Installation von ab, das Ausführen eines grundlegenden Tests, das Testen von POST-Endpunkten, das Lesen der Ausgabe und das Wissen, wann ab nicht mehr das richtige Werkzeug ist. Jeder Befehl hier entspricht einem Flag, das in der offiziellen Apache ab-Referenz dokumentiert ist.
Was ApacheBench ist und woher es kommt
ab ist ein Benchmarking-Client, der mit dem Apache HTTP Server gebündelt ist. Der Name ist eine Abkürzung für ApacheBench. Er öffnet Verbindungen zu einer URL, sendet Anfragen so schnell, wie es Ihre Parallelitätseinstellung erlaubt, misst die Zeit jeder Antwort und gibt eine Zusammenfassung aus.

Es misst eine Sache gut: wie viele Anfragen pro Sekunde ein einzelner Endpunkt bedienen kann und wie die Antwortzeit unter Last verteilt ist. Das sind Durchsatz und Latenz für eine URL.
Was es nicht tut, ist genauso wichtig. ab prüft nicht, ob der Antwortkörper korrekt ist. Es validiert kein Schema oder bestätigt ein Feld. Es durchläuft keinen mehrstufigen Ablauf wie Anmelden, Abrufen, Aktualisieren. Es ruft eine URL auf und zählt. Behalten Sie diesen Rahmen im Auge, und ab bleibt nützlich. Erwarten Sie mehr, und Sie werden enttäuscht sein.
Wenn Sie einen breiteren Überblick über die Disziplin wünschen, in die ab passt, lesen Sie was API-Lasttests sind und warum die API-Antwortzeit wichtig ist.
Installation von ab
ab wird mit den Apache-Dienstprogrammen gebündelt. Der Paketname variiert je nach Plattform.
Unter Debian und Ubuntu installieren Sie das Paket apache2-utils:
sudo apt-get update
sudo apt-get install -y apache2-utils
Unter CentOS, RHEL und Fedora ist das Paket httpd-tools:
# CentOS 7
sudo yum install -y httpd-tools
# Fedora and CentOS 8+
sudo dnf install -y httpd-tools
Unter macOS ist ab bereits vorhanden, da das System mit Apache geliefert wird. Überprüfen Sie dies:
ab -V
Sie sollten eine Versionszeile wie Version 2.3 sehen. Falls der Befehl unter macOS fehlt, installieren Sie ihn über Homebrews Apache-Formel. Sobald ab -V eine Version ausgibt, sind Sie bereit.
Ausführen eines grundlegenden Lasttests
Die beiden Flags, die Sie jedes Mal verwenden werden, sind -n und -c.
-n requestslegt die Gesamtzahl der auszuführenden Anfragen fest. Der Standardwert ist eine einzelne Anfrage, was Ihnen nichts sagt, setzen Sie diesen Wert also immer.-c concurrencylegt fest, wie viele Anfragen gleichzeitig ausgeführt werden. Der Standardwert ist eins, was vollständig seriell bedeutet.
Hier sind 1000 Anfragen, 50 gleichzeitig, an einen JSON-Endpunkt:
ab -n 1000 -c 50 https://api.example.com/v1/users
Beachten Sie den abschließenden Pfad. ab benötigt eine vollständige URL mit Pfad. Wenn Sie es auf einen reinen Host ohne Pfad richten, wird ein Fehler ausgegeben. Für das Root-Verzeichnis verwenden Sie einen abschließenden Schrägstrich: https://api.example.com/.
Echte Clients verwenden TCP-Verbindungen wieder, anstatt für jede Anfrage eine neue zu öffnen. Fügen Sie -k hinzu, um HTTP KeepAlive zu aktivieren, damit ab Verbindungen innerhalb einer Sitzung wiederverwendet:
ab -n 1000 -c 50 -k https://api.example.com/v1/users
Der -k-Lauf kommt dem Verhalten eines Browsers oder eines gut funktionierenden API-Clients in der Regel näher, da er die Kosten für den Verbindungsaufbau bei jeder Anfrage vermeidet. Vergleichen Sie die beiden Zahlen, um zu sehen, wie viel Ihrer Latenz auf den Verbindungs-Overhead zurückzuführen ist.
Sie können den Lauf auch nach Zeit statt nach Anzahl begrenzen. -t legt eine maximale Anzahl von Sekunden fest und impliziert intern -n 50000, sodass der Test bei der Grenze stoppt, die Sie zuerst erreichen:
ab -t 30 -c 50 -k https://api.example.com/v1/users
Das läuft bis zu 30 Sekunden bei einer Parallelität von 50. Praktisch, wenn Sie eine Messung mit fester Dauer statt einer festen Anzahl wünschen.
Testen eines POST-Endpunkts
Die meisten API-Arbeiten sind keine GET-Anfragen. Um eine POST-Anfrage zu testen, legen Sie den Anfragetext in einer Datei ab und übergeben ihn mit -p. Sie müssen auch den Content-Type mit -T festlegen, da der Server sonst den Text ablehnt.
Erstellen Sie die Nutzlast:
cat > payload.json <<'EOF'
{"name": "Ada Lovelace", "email": "ada@example.com"}
EOF
Senden Sie es dann:
ab -n 500 -c 25 -k \
-p payload.json \
-T application/json \
https://api.example.com/v1/users
Das -p-Flag benennt die Datei, die den POST-Body enthält. Das -T-Flag setzt den Content-Type-Header. Der Standard-Content-Type ist text/plain, was fast nie das ist, was eine JSON-API wünscht, setzen Sie -T application/json daher explizit.
Wenn Ihr Endpunkt Authentifizierung oder andere Header benötigt, fügen Sie diese mit -H hinzu. Wiederholen Sie das Flag für jeden Header:
ab -n 500 -c 25 -k \
-p payload.json \
-T application/json \
-H "Authorization: Bearer YOUR_TOKEN" \
https://api.example.com/v1/users
Für eine Auffrischung zum manuellen Erstellen von JSON-Anfragekörpern, siehe wie man JSON-Daten mit curl POSTet. Der gleiche Body funktioniert als ab-Nutzlastdatei.
Lesen der Ausgabe
Ein Durchlauf gibt einen Zahlenblock aus. Hier ist ein gekürztes Beispiel:
Concurrency Level: 50
Time taken for tests: 4.212 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 0
Requests per second: 237.42 [#/sec] (mean)
Time per request: 210.598 [ms] (mean)
Time per request: 4.212 [ms] (mean, across all concurrent requests)
Transfer rate: 142.31 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 5 18 9.4 16 64
Processing: 22 189 41.2 182 310
Waiting: 21 177 39.8 171 295
Total: 31 207 42.7 201 338
Percentage of the requests served within a certain time (ms)
50% 201
66% 221
75% 236
90% 268
95% 291
99% 324
100% 338 (longest request)
Lesen Sie zuerst diese Felder:
- Anfragen pro Sekunde ist Ihre Durchsatz-Schlagzeile. Es ist die Anzahl der Anfragen geteilt durch die Gesamtzeit. Höher ist besser.
- Fehlgeschlagene Anfragen und Nicht-2xx-Antworten sagen Ihnen, ob der Server die Last tatsächlich bewältigt oder Fehler ausgegeben hat. Eine hohe Anzahl von Anfragen pro Sekunde bedeutet nichts, wenn die Hälfte der Antworten 500er sind. Überprüfen Sie diese beiden immer, bevor Sie der Durchsatzangabe vertrauen.
- Zeit pro Anfrage erscheint zweimal. Die erste Zeile ist die mittlere Wartezeit eines einzelnen Benutzers (Parallelität mal Gesamtzeit geteilt durch Anfragen). Die zweite Zeile, bezeichnet als „across all concurrent requests“ (über alle parallelen Anfragen), ist der durchschnittliche Abstand zwischen abgeschlossenen Anfragen. Die erste Zahl ist die, die Benutzer wahrnehmen.
Die Tabelle Prozentsatz der Anfragen, die innerhalb einer bestimmten Zeit bedient wurden ist der nützlichste Teil. Es ist eine Perzentil-Aufschlüsselung. Die 50%-Zeile ist Ihr Median. Die 95%- und 99%-Zeilen zeigen den langsamen 'Tail'. Im Beispiel waren die Hälfte der Anfragen nach 201 ms abgeschlossen, aber 1% dauerte 324 ms oder länger. Tail-Latenz ist der Bereich, wo echte Benutzer betroffen sind, achten Sie also mehr auf das 95. und 99. Perzentil als auf den Durchschnitt.
Möchten Sie die Rohdaten pro Anfrage für ein Diagramm? Fügen Sie -e results.csv hinzu, um eine CSV-Datei mit Perzentil-Zeit-Paaren zu schreiben, oder -g results.tsv für eine gnuplot-freundliche Datei.
Wo ab aufhört, das richtige Werkzeug zu sein
ab ist bewusst eng gefasst. Seine Grenzen sollten klar dargelegt werden, damit Sie es nicht missbrauchen.
- Eine URL pro Lauf.
abbeansprucht einen einzelnen Endpunkt. Es kann keine Abfolge wie Authentifizieren, Ressource erstellen und dann zurücklesen skripten. Echte Benutzerpfade berühren viele Endpunkte nacheinander, undabhat kein Konzept dafür. - Keine Korrektheitsprüfungen.
abzählt Statuscodes und Byte-Längen. Es parst Ihr JSON nicht oder bestätigt, dass ein Feld einem erwarteten Wert entspricht. Eine Antwort kann strukturell falsch sein und trotzdem als Erfolg zählen. Lastzahlen sind kein Ersatz für eine bestandene Testsuite. - Veraltete HTTP-Handhabung. Die offiziellen Dokumente besagen, dass
abHTTP/1.x nicht vollständig implementiert und nur einige erwartete Antwortformen akzeptiert. Es hat keine HTTP/2-Unterstützung. Für Server, die sich unter HTTP/2 anders verhalten, wirdabdies nicht widerspiegeln. - Einzelmaschinenlast.
abläuft von einer einzigen Maschine und einem einzigen Prozess aus. Jenseits einer bestimmten Parallelität messen Sie die Grenzen Ihres eigenen Clients statt die des Servers. Die Dokumente warnen sogar davor, dassabs eigene Parsing-Logik in Profilen als Engpass erscheinen kann.
Nichts davon macht ab schlecht. Es macht es zu einem spezifischen Werkzeug: einer schnellen Durchsatzsonde für einen Endpunkt. Wenn Sie skriptgesteuerte Abläufe, verteilte Last oder HTTP/2 benötigen, greifen Sie zu einem dafür entwickelten Tool. JMeter bewältigt mehrstufige Szenarien und verteilte Läufe, und es gibt eine breitere Übersicht über Lasttest-Tools, wenn Sie Optionen vergleichen.
Wo Funktionstests passen
Durchsatz ist eine Achse. Korrektheit ist eine andere, und ab berührt diese nicht. Bevor Sie einen Endpunkt einem Lasttest unterziehen, möchten Sie wissen, dass er unter normalen Bedingungen die richtigen Daten in der richtigen Form zurückgibt. Das sind Funktions- und Vertragstests, und das ist eine andere Aufgabe.
Hier verdient eine vollständige API-Plattform ihren Platz neben ab. Apidog ermöglicht Ihnen den Aufbau von Testszenarien mit visuellen Behauptungen, das Verketten von Anfragen zu mehrstufigen Abläufen und die Validierung von Antworten anhand Ihres Schemas – all das, was ab konstruktionsbedingt nicht kann. Sie speichern diese Szenarien einmal und führen sie überall aus.
Für die kontinuierliche Integration führt die Apidog CLI Ihre gespeicherten Szenarien unbeaufsichtigt aus. Installieren Sie es mit Node:
npm install -g apidog-cli
Führen Sie dann ein gespeichertes Szenario oder eine Suite in einer ausgewählten Umgebung aus und erstellen Sie Berichte, die Ihre CI archivieren kann:
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
Das -t-Flag zielt auf ein gespeichertes Szenario, einen Ordner oder eine Suite anhand der ID ab. Das -e-Flag wählt die Umgebung aus. Das -r-Flag wählt einen oder mehrere Reporter aus cli, html, json und junit. Für datengesteuerte Läufe fügen Sie -d (oder --iteration-data) mit einem Datenpfad oder einer Testdaten-ID hinzu. Die CLI ist Headless und führt gespeicherte Szenarien aus, sodass sie in jeden CI-Schritt passt, der Node ausführen kann. Es ist kein Anfragengenerator und kein Lastgenerator; es führt die Funktionstests aus, für die ab nie gedacht war.
Ein gesundes Setup verwendet beides. Führen Sie Apidog-Szenarien aus, um zu beweisen, dass der Endpunkt korrekt ist. Führen Sie ab aus, um zu beweisen, dass er schnell genug ist. Für die Korrektheitsseite siehe den Apidog-Leistungstestleitfaden und das allgemeine Tutorial zum API-Leistungstest.
FAQ
Ist ApacheBench nur für Apache-Server?
Nein. Trotz des Namens sendet ab einfache HTTP- und HTTPS-Anfragen an jeden Server. Es funktioniert mit Nginx, Node, Go, Python oder jedem Host, der HTTP spricht. Die Verbindung zu Apache besteht nur darin, dass das Tool mit dem Apache HTTP Server ausgeliefert wird.
Welche Parallelität und Anzahl von Anfragen sollte ich verwenden?
Beginnen Sie niedrig und steigern Sie sich. Versuchen Sie -n 1000 -c 10, erhöhen Sie dann -c auf 25, 50, 100 und beobachten Sie, wo die Anfragen pro Sekunde nicht mehr steigen und fehlgeschlagene Anfragen auftreten. Dieser Wendepunkt ist ungefähr dort, wo der Endpunkt gesättigt ist. Passen Sie Ihre Spitzenparallelität dem erwarteten realen Datenverkehr an, anstatt eine große runde Zahl zu wählen.
Warum sind meine fehlgeschlagenen Anfragen hoch, obwohl die API einwandfrei funktioniert?
ab markiert eine Anfrage als fehlgeschlagen, wenn die Antwortlänge zwischen den Anfragen variiert, was für dynamisches JSON normal ist. Fügen Sie das -l-Flag hinzu, um Längenunterschiede nicht als Fehler zu zählen. Überprüfen Sie dann die Zeile der Nicht-2xx-Antworten, um zu sehen, ob darunter echte Fehler liegen.
Kann ab einen Endpunkt testen, der ein Login-Token benötigt?
Ja, wenn Sie bereits ein Token haben. Übergeben Sie es mit -H "Authorization: Bearer YOUR_TOKEN". Was ab nicht kann, ist sich zuerst anzumelden, um ein frisches Token zu erhalten, und es dann zu verwenden. Das ist ein mehrstufiger Ablauf, und dafür benötigen Sie ein szenariobasiertes Tool wie Apidog.
Unterstützt ab HTTP/2?
Nein. ab spricht HTTP/1.x und implementiert, laut offizieller Dokumentation, nicht einmal dies vollständig. Wenn das Verhalten Ihres Servers unter HTTP/2 wichtig ist, verwenden Sie stattdessen ein Lasttest-Tool mit HTTP/2-Unterstützung.
