Systematischer Ansatz für Lasttests: Von Token-Fehlern zu stabilen Metriken
Das Backend, das als Proxy zwischen Frontend und einem externen Dienst fungiert, speicherte ein Zugriffstoken über opcache. Unter Last erkannten mehrere parallele Anfragen gleichzeitig ein abgelaufenes Token und versuchten, es zu aktualisieren. Das alte Token überschrieb das frische im Cache, was zu 403-Fehlern führte.
Lösung: Wir fügten eine Sperre für die Token-Aktualisierung hinzu und verlagerten den Cache auf geclustertes Memcached für einen einheitlichen Zustand über Prozesse hinweg. Tests in Postman mit parallelen Anfragen bestätigten, dass die Race Condition beseitigt wurde.
Metriken vorher: Antwortzeit wuchs exponentiell, Erfolgsrate fiel unter 90% bei 300 RPS. Nachher: Erfolgsrate 100%, 5xx-Fehler <0,05%, durchschnittliche Antwortzeit 99-104 ms bei 226 RPS.
Backend-Vorbereitung: Optimierungs-Checkliste
Vor Lasttests (LT) folgt ein Backend-Entwickler einer systematischen Checkliste. Dies minimiert Engpässe auf Code- und Infrastrukturebene.
Datenbankoptimierung
- Indizieren Sie alle Felder in WHERE- und JOIN-Klauseln.
- Analysieren Sie EXPLAIN für langsame Abfragen.
- Master-Slave-Replikation, Verbindungspooling (z.B. pgbouncer oder Äquivalent).
Caching
- Memcached für wiederkehrende Daten.
- HTTP-Antwort-Caching in Varnish oder nginx.
- Twig-Template-Caching.
Asynchrone Verarbeitung
- RabbitMQ- oder Redis-Warteschlangen für Hintergrundaufgaben.
- Auslagern von E-Mail-Versand, PDF-Generierung in Hintergrundjobs.
PHP-Code
- Beseitigen Sie N+1-Abfragen.
- Optimieren Sie Schleifen, vermeiden Sie tiefe Rekursion.
- Speicher freigeben mit unset() für große Objekte.
Infrastruktur
- php-fpm: pm.max_children > 100, pm.max_requests = 500.
- MinIO für Dateispeicher.
- HPA in Kubernetes basierend auf CPU/RAM.
- Ratenbegrenzer (nginx oder Traefik) für Drosselung.
Frontend: Reduzierung der eingehenden Last
Das Frontend erzeugt den Hauptverkehr. Optimierungen hier können Backend-RPS um 30-50% reduzieren.
- Statische Assets: nginx-Cache für JS/CSS/Bilder.
- Client-seitiger API-Cache: localStorage oder Memcached für selten ändernde Daten (z.B. Kataloge, Konfigurationen).
- Paginierung: Verwenden Sie limit/offset oder Infinite Scroll statt vollständiger Datenladungen.
- SSG/ISR: Next.js für statisches Seiten-Rendering.
- SSE/Webhooks: Ersetzen Sie Polling durch Push-Benachrichtigungen.
Lasttest-Workflow
LT ist obligatorisch für Features, die Serverlogik, Caching oder Datenbanken ändern. Führen Sie es auf Staging/Produktion nachts bei minimaler Benutzerlast durch.
- Planung (eine Woche im Voraus): Lead + PM + DevOps schätzen Ziel-RPS (N Anfragen/Sekunde).
- DevOps-Rolle: Konfigurieren Sie Pods (CPU/RAM), HPA, Echtzeit-Monitoring.
- Ausführung: Verwenden Sie k6 oder Ähnliches, mit Szenarien für API-Endpunkte.
- Monitoring: Grafana (RPS, Latenz, Fehlerrate), Graylog für Logs.
- Analyse: Identifizieren Sie Degradationspunkte, beheben Sie Engpässe, wiederholen Sie.
Erfolgskriterien: Erfolgsrate >99%, Latenz <150 ms bei Ziel-RPS mit 20% Puffer.
Wichtige Erkenntnisse
- Prozess-Race-Conditions (z.B. Tokens, Sessions) werden nur unter paralleler Last sichtbar.
- Geclusterter Cache (Memcached) statt lokalem opcache verhindert Race Conditions.
- LT auf produktionsähnlichen Umgebungen: Datenbankreplikation, externe Dienste.
- DevOps im Loop: Ressourcen während Tests dynamisch anpassen.
- Frontend-Optimierungen reduzieren Last effektiver als Backend-Korrekturen.
Erfolgsmetriken und Benchmarks
Beispiel aus Grafana nach Korrekturen:
| Metrik | Durchschnitt | Spitze | Ziel |
|--------|---------|------|--------|
| Erfolgsrate | 100% | 100% | >99% |
| 5xx-Fehler | 0,017% | 0,042% | <0,1% |
| RPS | 226 | 321 | 300+ |
| Latenz (ms) | 99-104 | 123 | <150 |
Stabilisierung bei 226 RPS ohne Degradation. Ausfallpunkt: ~450 RPS (100% Puffer).
Empfehlungen für Middle/Senior-Entwickler
- Integrieren Sie LT in CI/CD: automatisierte Tests bei Merge.
- Überwachen Sie p99-Latenz, nicht nur Durchschnitt.
- Testen Sie Worst-Case-Szenarien: 80% Verkehr auf einem einzelnen Endpunkt.
- Protokollieren Sie Request-IDs für Tracing (z.B. Jaeger/OpenTelemetry).
Dieser Ansatz identifiziert Probleme während der Entwicklung und reduziert Vorfälle in der Produktion.
— Editorial Team
Noch keine Kommentare.