Testowanie wydajności serwera — k6, ApacheBench i wrk
Opublikowano: 9 kwietnia 2026 · Kategoria: VPS / Wydajność
Kupujesz droższy VPS bo aplikacja "działa wolno"? Zanim przepłacisz, zmierz gdzie leży faktyczny bottleneck. Load testing pozwala zmierzyć ile requestów na sekundę obsługuje Twój stack, jakie jest P95 latencji i przy ilu użytkownikach jednocześnie serwis zaczyna się sypać. W tym przewodniku poznasz trzy narzędzia: ApacheBench do szybkich benchmarków, wrk do wielowątkowych testów i k6 do złożonych scenariuszy z integracją CI/CD.
ApacheBench (ab) — szybki benchmark w jednej komendzie
ab jest wbudowany w pakiet apache2-utils — nie wymaga instalacji serwera
Apache. Działa jako klient HTTP wysyłający N żądań z C równoległymi połączeniami:
sudo apt install -y apache2-utils # Składnia: ab -n LICZBA_ŻĄDAŃ -c RÓWNOLEGŁOŚĆ URL # Test: 1000 żądań, 10 równolegle ab -n 1000 -c 10 https://example.com/ # Test z nagłówkiem (np. autoryzacja) ab -n 500 -c 20 -H "Authorization: Bearer TOKEN" https://api.example.com/v1/products # Test POST z body JSON ab -n 200 -c 5 \ -T 'application/json' \ -p payload.json \ https://api.example.com/v1/orders # Zapisz wyniki do pliku CSV (gnuplot friendly) ab -n 1000 -c 50 -e results.csv https://example.com/
Przykład wyjścia ab z kluczowymi metrykami:
Concurrency Level: 50 Time taken for tests: 3.241 seconds Complete requests: 1000 Failed requests: 0 Requests per second: 308.55 [#/sec] (mean) Time per request: 162.06 [ms] (mean) Time per request: 3.24 [ms] (mean, across all concurrent requests) Transfer rate: 412.33 [Kbytes/sec] received Percentage of the requests served within a certain time (ms) 50% 98 66% 112 75% 124 80% 134 90% 178 95% 234 98% 312 99% 389 100% 621 (longest request)
Interpretacja: 308 RPS (requests per second), mediana 98ms, P95 = 234ms (95% żądań odpowiedziało w <234ms), maksimum 621ms. Dla normalnej strony statycznej: 1000+ RPS to dobry wynik na małym VPS. Dla PHP/Node.js: 100–500 RPS zależy od złożoności.
wrk — wielowątkowy benchmark HTTP
wrk jest szybszy od ab bo używa wielu wątków i asynchronicznych połączeń (epoll/kqueue).
Idealny do sprawdzenia maksymalnej przepustowości serwera:
# Instalacja wrk sudo apt install -y wrk # lub build ze źródeł: # git clone https://github.com/wg/wrk && cd wrk && make # Podstawowy test: 4 wątki, 100 połączeń, przez 30 sekund wrk -t4 -c100 -d30s https://example.com/ # Z niestandardowym nagłówkiem i timeoutem wrk -t4 -c100 -d30s \ -H "Accept-Encoding: gzip" \ --timeout 10s \ https://example.com/api/products # Skrypt Lua — POST request z JSON body wrk -t4 -c100 -d30s -s post.lua https://api.example.com/v1/data
-- post.lua — skrypt Lua dla wrk
wrk.method = "POST"
wrk.body = '{"user":"test","action":"login"}'
wrk.headers["Content-Type"] = "application/json"
-- Opcjonalnie: losowe dane per request
local counter = 0
request = function()
counter = counter + 1
local body = '{"id":' .. counter .. '}'
return wrk.format(nil, nil, nil, body)
end # Wynik wrk:
Running 30s test @ https://example.com/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 45.23ms 12.34ms 234.56ms 89.12%
Req/Sec 543.21 45.67 612.00 78.45%
65123 requests in 30.03s, 89.45MB read
Requests/sec: 2168.23
Transfer/sec: 2.98MB k6 — load testing ze skryptami JavaScript
k6 (od Grafana Labs) to nowoczesne narzędzie do load testingu — testy piszesz w JavaScript, możesz modelować złożone scenariusze użytkowników i integrować z CI/CD przez thresholds:
# Instalacja k6 (Ubuntu/Debian) sudo gpg -k sudo gpg --no-default-keyring \ --keyring /usr/share/keyrings/k6-archive-keyring.gpg \ --keyserver hkp://keyserver.ubuntu.com:80 \ --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" \ | sudo tee /etc/apt/sources.list.d/k6.list sudo apt update && sudo apt install -y k6
Skrypt k6 z VU (virtual users), stages i thresholds — zapisz jako test.js:
import http from 'k6/http';
import { check, sleep } from 'k6';
// Opcje testu
export const options = {
// Stages — ramp-up, plateau, ramp-down
stages: [
{ duration: '30s', target: 10 }, // Ramp-up do 10 VU w 30s
{ duration: '1m', target: 50 }, // Skaluj do 50 VU przez 1 min
{ duration: '30s', target: 50 }, // Utrzymaj 50 VU przez 30s
{ duration: '30s', target: 0 }, // Ramp-down do 0
],
// Thresholds — kryteria sukcesu testu
thresholds: {
'http_req_duration': ['p(95)<500'], // P95 < 500ms
'http_req_failed': ['rate<0.01'], // Mniej niż 1% błędów
'checks': ['rate>0.99'], // >99% własnych checków OK
},
};
// Domyślna funkcja — jeden wirtualny użytkownik
export default function () {
// Test strony głównej
const homeRes = http.get('https://example.com/');
check(homeRes, {
'homepage: status 200': (r) => r.status === 200,
'homepage: < 300ms': (r) => r.timings.duration < 300,
'homepage: has title': (r) => r.body.includes('<title>'),
});
sleep(1); // 1 sekunda przerwy między iteracjami
// Test API
const apiRes = http.get('https://example.com/api/products', {
headers: { 'Accept': 'application/json' },
});
check(apiRes, {
'API: status 200': (r) => r.status === 200,
'API: JSON body': (r) => r.headers['Content-Type'].includes('json'),
'API: < 500ms': (r) => r.timings.duration < 500,
});
sleep(2);
} # Uruchom test k6 run test.js # Eksport wyników do JSON (dla dalszej analizy) k6 run --out json=results.json test.js # Integracja z Grafana (przez k6 Cloud lub InfluxDB) k6 run --out influxdb=http://localhost:8086/k6 test.js
Porównanie narzędzi load testowych
| Narzędzie | Język skryptów | Złożoność scenariuszy | CI/CD | Kiedy używać |
|---|---|---|---|---|
| ApacheBench (ab) | Brak (CLI) | Jeden endpoint | Tak (exit code) | Szybki benchmark, porównanie konfiguracji |
| wrk | Lua (opcjonalnie) | Jeden endpoint + custom headers | Ograniczone | Maksymalna przepustowość, wielowątkowy test |
| k6 | JavaScript/TypeScript | Złożone scenariusze | Pełna (thresholds) | Testy wieloetapowe, CI/CD, SLA verification |
| Locust | Python | Złożone scenariusze | Tak | Zespoły znające Python, distributed testing |
| JMeter | XML + Groovy | Pełne | Tak | Enterprise, protokoły nie-HTTP (JDBC, JMS) |
Interpretacja wyników — co oznaczają metryki
- RPS (Requests per Second) — przepustowość serwera. Dla API REST: 500–5000 RPS to norma w zależności od złożoności. Dla statycznych plików: 10 000+ RPS na dobrym serwerze.
- P50 (mediana) — połowa żądań odpowiedziała szybciej. Dobry punkt odniesienia dla "typowego użytkownika".
- P95 / P99 — 95% / 99% żądań odpowiedziało szybciej. P99 > 2× P95 sugeruje outliers — wolne zapytania SQL, cold starts, GC pause.
- Error rate — procent żądań zakończonych błędem (5xx, timeout). Powyżej 1% to alarm. Powyżej 5% to katastrofa produkcyjna.
- Throughput vs Latency — wzrost obciążenia zazwyczaj zwiększa latencję. Znajdź punkt "knee of the curve" — gdy latencja zaczyna rosnąć nieliniowo.