...

Warum HTTP Requests blockieren können, obwohl genug Ressourcen vorhanden sind

HTTP Requests können blockieren, obwohl CPU, RAM und Bandbreite offen wirken, weil unsichtbare Limits, Filter und Warteschlangen entlang der gesamten Kette greifen. Ich erkläre, wo Grenzen entstehen, wie sie wirken und welche Einstellungen ich so setze, dass Anfragen wieder flüssig durchlaufen.

Zentrale Punkte

Bevor ich ins Detail gehe, fasse ich die wichtigsten Ursachen zusammen und nenne, worauf ich zuerst schaue. Diese Punkte decken die typischen Engstellen ab, die trotz freier Ressourcen zum Stau führen. Ich halte die Liste bewusst kompakt, damit Sie sofort Ansatzpunkte prüfen können. Entscheidend ist, dass jede Schicht eigene Regeln hat, die unabhängig von CPU und RAM greifen. Wer diese Regeln kennt, löst viele „unerklärliche“ Wartezeiten schnell auf.

  • Worker-Limits: Zu wenige Prozesse/Threads blocken neue Verbindungen trotz freier CPU.
  • Sicherheitslayer: WAF/Webfilter sperren Muster, Methoden oder Clients, oft ohne hohe Last.
  • Concurrency: PHP-FPM, Datenbank und Proxies begrenzen gleichzeitige Sessions.
  • Keep-Alive/Timeouts: Lange Verbindungen binden Slots, Requests landen in Queues.
  • Client-Filter: Browser-Extensions stoppen Anfragen, bevor sie den Server erreichen.

Diese Eckpunkte reichen oft, um das Verhalten zielgerichtet zu prüfen. Ich zeige im Folgenden, wie ich daraus konkrete Maßnahmen ableite und Blockaden sauber eingrenze.

Warum HTTP-Requests trotz freier Ressourcen blockieren

Ein Request durchläuft mehrere Schichten: Client, Netzwerk, Filter, Webserver, Laufzeitumgebung und Datenbank. Jede Schicht bringt eigene Limits mit, die unabhängig von CPU, RAM oder Bandbreite greifen. Sind Worker-Slots belegt oder Regeln aktiv, wartet der Request in einer Queue oder fliegt sofort raus. Diese Wartezeit taucht in klassischen Ressourcen-Diagrammen oft gar nicht auf. Genau das führt zu der Fehleinschätzung, der Server sei „leer“, obwohl Anfragen nicht beantwortet werden.

Sicherheitslayer: WAF, Filter und Provider-Regeln

Viele Blockaden entstehen, bevor die Anwendung überhaupt läuft. Web Application Firewalls, IDS/IPS und providerseitige Filter erkennen Muster und bremsen oder sperren sie [1][5][9]. Dabei reichen verdächtige Parameter, alte Protokolle oder Methodenkombinationen aus, um eine Sperre zu zünden. Aus Betreiber-Sicht wirkt das wie ein Serverfehler, doch die Entscheidung fällt „upstream“. Ich prüfe deshalb Protokolle der WAF und notiere Request-ID, IP, Zeit und Statuscode. Mit diesen Daten lässt sich die Regel identifizieren und gezielt anpassen, ohne die Sicherheit über Bord zu werfen.

Client-Seite: Browser-Extensions und lokale Blocker

Nicht jede Anfrage erreicht den Server. Adblocker, Passwort-Manager und Script-Blocker stoppen URLs bereits im Browser; die DevTools zeigen dann „Requests to the Server Have Been Blocked by an Extension“ [3][7]. Ich teste in einem privaten Fenster, deaktiviere Erweiterungen und prüfe, ob der Request überhaupt gesendet wurde. Zusätzlich hilft es, Prioritäten im Frontend zu steuern, etwa mit einer sauberen Request-Priorisierung für kritische Assets. So verhindere ich, dass unkritische Third-Party-Calls wichtige Routen verzögern.

Methode und Routing: 405, 403, 429 verstehen

Ein 405 „Method Not Allowed“ zeigt klar: Der Server kennt die Ressource, erlaubt die verwendete Methode aber nicht [5]. Ebenso deuten 403 auf Filter oder Rechte und 429 auf aktives Rate-Limiting. In Logs erkenne ich schnell, ob eine globale Regel Methoden wie PUT oder DELETE sperrt oder ob ein Endpoint nie implementiert wurde. Ich passe dann Routing, Controller oder die WAF-Regel an. So löst sich vermeintliches „Blocking“ in eine saubere Korrektur von Methoden und Pfaden auf.

Webserver-Architektur und Worker-Limits

Apache, NGINX, LiteSpeed und OpenLiteSpeed handhaben Verbindungen unterschiedlich [4]. Entscheidend sind Anzahl der Worker-Prozesse, Threads und wie Keep-Alive-Sockets Slots belegen. Sind alle Worker durch lange Verbindungen belegt, wandern neue Requests in eine Queue, obwohl CPU und RAM frei wirken. Ich werte deshalb Verbindungszustände aus und passe Worker, Backlog und Keep-Alive-Zeiten an. Hintergrundwissen zu Warteschlangen hilft, etwa beim Thema Server-Queueing und Latenz.

Schicht Relevantes Limit Typisches Symptom Diagnosehinweis
Webserver Worker-/Thread-Zahl Warteschlangen, 503 unter Last Status-Module, Verbindungszustände prüfen
PHP-FPM/FastCGI max_children / pm Hängende Requests, hohe Time-to-First-Byte FPM-Logs, Slow Log, Prozessanzahl
Datenbank max_connections Fehler „Too many connections“ SHOW PROCESSLIST, Connection-Peaks
WAF/Filter Signaturen, Methoden 403/405, kaputte Formular-Posts WAF-Logs, Regel-Hit-IDs
Load Balancer Per-Backend-Conn-Limit Uneinheitliche Antwortzeiten LB-Stats, Backend-Health

Concurrency in PHP-FPM, Datenbank und Proxies

Oft platzt die gleichzeitige Verarbeitung zuerst in der Laufzeitumgebung. Sind alle PHP-FPM-Worker beschäftigt, steht kein Slot für neue Skripte bereit; die Anfragen warten, obwohl die CPU kaum arbeitet. Ähnlich verhält es sich bei Datenbanken mit max_connections oder bei Proxies mit Verbindungsgrenzen pro Backend. Ich optimiere zuerst die Dauer einzelner Requests, bevor ich Limits erhöhe. So verkürze ich die Belegzeit pro Slot und senke die Wahrscheinlichkeit, dass Queues anwachsen.

Langsame Backends und PHP-Session-Locking

Lange Datenbankabfragen, externe APIs oder Datei-I/O binden Worker deutlich länger. Zusätzlich kann Session-Locking ganze Ketten verlangsamen, etwa bei WordPress-Logins oder Warenkörben. Ich prüfe, ob parallele Requests an dieselbe Session-ID nacheinander statt gleichzeitig laufen. Wenn ja, setze ich auf gezieltes Unlocking, reduziere kritische Schreibzugriffe und folge praxiserprobten Hinweisen zum PHP-Session-Locking. Dadurch befreie ich Slots schneller und reduziere Wartezeiten spürbar.

Timeouts, Keep-Alive und Verbindungs-Strategien

Zu lange Keep-Alive-Zeiten binden Ressourcen, zu kurze erzeugen Handshakes und Latenz. Ich wähle Werte passend zum Traffic-Profil und setze Limits für Header-, Body- und Backend-Timeouts. Wichtig ist, Timeouts nicht nur am Webserver zu definieren, sondern einheitlich entlang der Kette: Proxy, App, Datenbank. Zusätzlich verhindere ich Idle-Blocking durch feinere HTTP/2-/HTTP/3-Settings und Priorisierung. So bleiben Slots verfügbar, ohne dass Clients dauernd neu verbinden müssen.

Hosting-Modelle: Shared, VPS, Dedicated

Shared-Hosting setzt frühe Filter und harte Kontingente, damit die Plattform fair bleibt [1]. Auf VPS isolieren Anbieter CPU und RAM, behalten aber Limits für I/O, Netzwerk oder Sicherheit bei; Unterschiede in Performance und Monitoring sind deutlich [10]. Auf Dedicated-Servern trage ich die volle Verantwortung für Webserver, Datenbank und WAF-Konfiguration. Vergleiche zeigen, dass moderne Stacks mit HTTP/3, NVMe und DDoS-Schutz klare Vorteile bringen [2][6][11][8]. Wer hohe Parallelität braucht, profitiert von klar dokumentierten Grenzen und Support, der bei Regel-Feinheiten hilft.

Systematische Analyse: Schritt für Schritt

Ich starte an der Quelle: Senden DevTools den Request wirklich, oder blockt eine Erweiterung [3][7]? Danach sehe ich mir Statuscodes an: 403/405/429/503 geben starke Hinweise auf Filter, Methoden oder Kapazität [5]. Parallel prüfe ich Logs von Webserver, App und WAF, um Muster und wiederkehrende Signaturen zu finden [1][9]. Anschließend kontrolliere ich Worker-Zahlen, FPM-Parameter, Keep-Alive und Datenbank-Connections und erhöhe Limits testweise mit Messpunkten davor und danach. Krönend simuliere ich Last, beobachte Engstellen in Echtzeit und verifiziere, dass die Warteschlangen schrumpfen.

Best Practices gegen Blockaden

Ich formuliere Concurrency-Ziele pro Schicht und setze Limits so, dass Lastspitzen abgefedert werden. Der Webserver muss zum Traffic-Muster passen; Benchmarks helfen bei der Wahl und Konfiguration [4]. Backends optimiere ich zuerst logisch: schnellere Queries, kürzere Transaktionen, weniger serielle Abschnitte. Sicherheitsregeln halte ich scharf genug gegen Angriffe, aber mit Ausnahmen für legitime Muster. Monitoring endet nicht bei CPU/RAM: Ich schaue auf Verbindungen, Queues, Response-Zeiten und Fehlercodes, damit Engstellen sichtbar bleiben [6][11].

Praxis-Notizen: request blocking hosting

In Shared-Umgebungen landen Blockaden häufig vor dem eigentlichen Webspace; Support braucht dann konkrete Request-Daten, um Regeln zu justieren [1]. Auf VPS skaliere ich schrittweise: mehr Worker, passendere Keep-Alive-Werte und engere Überwachung der Datenbank [10]. Auf eigener Hardware entscheide ich über Load-Balancing, WAF-Regeln und Limits pro Backend. Projekte mit stark parallelen Zugriffen profitieren von sauberer HTTP/2-/HTTP/3-Konfiguration und klaren Reserven für Spitzen. Wer Wachstum erwartet, plant den Wechsel auf leistungsfähigere Tarife frühzeitig ein und spart später viel Tuning-Aufwand [2][6][10][11].

Netzwerk- und Kernel-Limits: Backlog, Ports und Deskriptoren

Neben Webserver und App limitiert der Kernel, wie viele Verbindungen gleichzeitig ankommen, aufgebaut und verwaltet werden. Ich prüfe zuerst den Listen-Backlog: Selbst wenn der Webserver viele Worker hat, kann die Accept-Queue knapp sein. Das Zusammenspiel aus Anwendung (listen backlog), Kernel (somaxconn) und SYN-Backlog (tcp_max_syn_backlog) bestimmt, ob Verbindungen in der Warteschlange bleiben oder verworfen werden. Symptome sind steigende Connect-Zeiten und Retransmits – bei niedriger CPU-Auslastung. Ich gleiche die Werte ab und messe die tatsächliche Auslastung der Queues, um Drops zu vermeiden.

Ein weiterer Klassiker ist die conntrack-Tabelle bei NAT/Firewall-Setups. Ist sie voll, verschwinden Verbindungen „spurlos“; die Anwendung sieht nie einen Request. Ich erkenne das an Meldungen im Systemlog und an sprunghaften Timeouts bei Lastspitzen. Gegenmaßnahmen sind: passende Größe der Tabelle, realistische Idle-Timeouts für Protokolle, weniger unnötige NAT-Wege und effiziente Keep-Alives, die Verbindungen sinnvoll wiederverwenden.

Ich prüfe außerdem die Zahl offener Dateideskriptoren (ulimit -n). Treffen viele gleichzeitige Sockets und Dateien auf restriktive Limits, schlägt Accept fehl („too many open files“) und neue Anfragen stauen sich davor. Der Fix ist meist banal: die nofile-Limits für Webserver, Proxy und Datenbank auf ein gesundes Niveau bringen – und zwar persistent, nicht nur interaktiv.

In stark parallelen Setups beobachte ich die Ephemeral-Port-Range und TIME_WAIT-Zustände. Gerade hinter NAT-Gateways erschöpfen sich die verfügbaren Quellports, wenn kurze Verbindungen massenhaft aufgebaut werden. Ich setze daher auf Verbindungswiederverwendung (Keep-Alive, HTTP/2/3), reduziere unnötige Kurzlebigkeit und tune TIME_WAIT-Handling vorsichtig, ohne die Stabilität zu riskieren. Das Ergebnis: weniger Port-Exhaustion und stabilere Connect-Zeiten unter Last.

Auf der Netzwerkkarte prüfe ich Queue-Längen, Offloading-Settings und IRQ-Verteilung. Ungleich verteilte Interrupts oder überlastete Queues erzeugen Latenzspitzen, die in Application-Logs nicht auffallen. Mit ausgewogenem IRQ-Balancing und sinnvollen Qdisc-Einstellungen (Stichwort Bufferbloat) reduziere ich Latenz, ohne die Bandbreite einzuschränken.

HTTP/2 und HTTP/3: Multiplexing richtig nutzen

Multiplexing löst viele Probleme, bringt aber neue Grenzen mit: Maximale Stream-Zahlen, Flow-Control-Fenster und Idle-Timeouts gelten pro Verbindung. Ist der Wert für gleichzeitige Streams zu niedrig, „hängen“ neue Anfragen, obwohl die TCP- oder QUIC-Verbindung steht. Ich prüfe daher, wie viele kritische Ressourcen parallel geladen werden müssen und passe die Stream-Limits vorsichtig an. Gleichzeitig achte ich auf vernünftige Flow-Control-Fenster, damit große Antworten nicht gedrosselt werden.

HTTP/2 multiplexer über TCP kann bei Paketverlusten unter Head-of-Line-Blocking leiden; HTTP/3 auf QUIC umgeht das, verlangt aber saubere TLS-/ALPN-Settings und stabile Path-Handling-Regeln. Ich teste beide Pfade und wähle gezielt die Protokolle, die zum Traffic-Profil passen. Wichtig: Priorisierung nicht blind vertrauen – Browser und Server interpretieren sie unterschiedlich. Ich fokussiere auf kritische Routen und prüfe, ob Prioritäten tatsächlich greifen und Slots nicht von langlaufenden Nebenströmen belegt werden.

CORS, Preflights und Header-/Body-Grenzen

Nicht jeder 4xx-Fehler kommt vom Server. CORS-Verstöße entstehen im Browser und zeigen sich in der Konsole, nicht im Access-Log. Ich verifiziere, ob Preflight-Requests (OPTIONS) korrekt beantwortet werden und ob WAF/Proxies diese Methode erlauben. Fehlen Header wie Access-Control-Allow-Methods/-Headers, „blockt“ der Browser die Antwort – ganz ohne Serverlast.

Ein weiterer Engpass: Header- und Cookie-Größen. Überwachsene Cookies, viele Vary-Header oder große Referer-Linien führen zu 431-Fehlern oder stillen Drops durch Puffergrenzen. Ich begrenze Cookie-Ballast, konsolidiere Header und setze Puffergrößen konsistent entlang der Kette. Für Uploads achte ich auf Body-Limits, 100-Continue-Handling und konsistente Chunked-Encoding-Unterstützung bei allen Proxies. Stimmen die Body- und Upload-Limits nicht überein, warten Clients auf eine Freigabe, die nie kommt – Requests bleiben scheinbar „hängen“.

DNS und TLS: Handshakes als versteckte Latenz

DNS-Auflösung und TLS-Aushandlung sind häufige Blindspots. Mehrfache CNAME-Ketten, langsame Resolver oder IPv6/IPv4-Mismatch verlängern die Startzeit, ohne CPU zu beanspruchen. Ich reduziere unnötige DNS-Sprünge, setze sinnvolle TTLs und sorge für schnelle Resolver-Pfade. Auf TLS-Seite prüfe ich Zertifikatsketten, aktivierte Cipher-Suites, OCSP-Stapling und Session-Resumption. Ein sauberer ALPN-Handshake verhindert Downgrades auf HTTP/1.1, die Keep-Alive-Slots stärker belasten. Ergebnis: kürzere Time-to-First-Byte und stabilere Parallelität, insbesondere auf Mobilnetzen.

CDN/Edge: Caching, Rate-Limits und IP-Reputation

Zwischen Client und Origin entscheiden CDNs, Reverse-Proxies und DDoS-Schutzsysteme über Durchlass und Drossel. Ich prüfe, ob kritische Routen korrekt gecacht werden (stale-while-revalidate, stale-if-error) und ob negative Caches Fehler länger festhalten als nötig. Rate-Limits, Bot-Management und IP-Reputation können legitimen Traffic dämpfen, insbesondere bei geteilten Netzen oder starkem API-Zugriff. Ich segmentiere Traffic (z. B. API vs. Assets), definiere klare Cache-Keys und entschärfe Regeln selektiv für vertrauenswürdige Clients. So entlaste ich den Origin und verhindere, dass CDN-Queues wachsen, während der Server „unterfordert“ aussieht.

Container und Orchestrierung: cgroups, Ingress und conntrack

In Containern gelten cgroup-Limits für CPU, RAM, pids und Dateien. Ein zu enger CPU-Quota führt zu Throttling: Prozesse warten auf CPU-Zeit, obwohl der Host frei ist. Ich kontrolliere Quotas und stelle sicher, dass Ingress/Proxy-Pods genug File-Deskriptoren und Puffer haben. In Kubernetes prüfe ich Ingress-Timeouts, Readiness/Liveness-Probes und Service-Implementierungen (IPVS), denn fehlerhafte Probes oder Timeouts erzeugen Zickzack-Latenz und unnötige Restarts.

Ein häufig übersehener Engpass ist die NAT-/conntrack-Kapazität je Node. Viele kurzlebige Verbindungen (z. B. egress zu externen APIs) füllen die conntrack-Tabelle, dann „verschwinden“ Requests im Netz. Ich skaliere die Tabelle, setze realistische Timeouts und bündele externe Calls, damit weniger neue Verbindungen entstehen. PodDisruptionBudgets, Rolling Updates und HPA-Skalierung plane ich so, dass zu Spitzenzeiten keine Kapazität vom Scheduler abgezogen wird – ansonsten bilden sich Queues, obwohl die App theoretisch genug Worker hätte.

Observability: Korrelation, Tracing und aussagekräftige Metriken

Um Blockaden schnell zu finden, brauche ich durchgehende Korrelation. Ich vergebe Request-IDs (z. B. traceparent) an Edge, Webserver, App und Datenbank und schreibe sie in die Logs. So sehe ich, ob eine Anfrage an der WAF scheitert, am Webserver wartet, im FPM-Queue hängt oder in der Datenbank blockiert. Ich arbeite mit Histograms statt reiner Durchschnittswerte und beobachte P95/P99-Latenz, offene Verbindungen, Accept-Queue, FPM-Queue-Länge, aktive DB-Sessions und Backend-Fehlercodes. Ergänzend nutze ich synthetische Checks, um Client-seitige Effekte von Server-seitigen klar zu trennen.

Bei Anomalien nutze ich ein Drilldown-Vorgehen: erst Edge/WAF-Logs, dann Load-Balancer, dann Webserver Access/Error, dann App- und FPM-Logs und zuletzt DB- und System-Logs. Dieser Pfad zeigt mir exakt, wo die Zeit verloren geht und an welcher Grenze der Request stoppt. Mit gezielten Metriken pro Schicht vermeide ich Bauchgefühl und reduziere die Zeit bis zur Ursache drastisch.

Tuning-Playbook und Checkliste

Für die Praxis halte ich ein kompaktes Playbook bereit, das ich an das Umfeld anpasse:

  • Reproduzierbarkeit: Szenario festnageln (Route, Methode, Größe, Client), Zeitstempel und IDs protokollieren.
  • Schichtweise prüfen: Browser/Extensions, CORS/Preflight, WAF-Hits, LB-Stats, Webserver-Status, FPM-Queue, DB-Active/Locks.
  • Queues sichtbar machen: Accept-/SYN-Backlog, FPM listen queue, Proxy-Backlog, DB-Connection-Pool.
  • Limits abgleichen: Worker/Threads, somaxconn, nofile, max_connections, Stream-Limits für H2/H3, Body-/Header-Limits, Timeouts.
  • Belegzeit senken: Queries beschleunigen, Session-Locks vermeiden, I/O reduzieren, Responses komprimieren und sinnvoll cachen.
  • Strategien harmonisieren: Keep-Alive-Dauer, HTTP/2-/3-Parametrisierung, Priorisierung kritischer Routen.
  • Sicherheit justieren: WAF-Regeln gezielt ausnehmen statt global schwächen; Logging mit Hit-IDs.
  • Skalierung: Concurrency pro Schicht definieren, Lasttests fahren, Reserven nachmessen, Limits erst nach Optimierung erhöhen.
  • Fallbacks: Circuit-Breaker für langsame Backends, Retry-Politik mit Jitter, „stale-if-error“ für kritische Assets.

Kurz zusammengefasst

Blockierte Anfragen bei freier CPU und RAM entstehen meist durch Limits, Filter und Verbindungs-Strategien – nicht durch fehlende Leistung. Ich prüfe zuerst, wo der Request stoppt: Browser, WAF, Webserver, Laufzeit oder Datenbank. Dann minimiere ich Belegzeiten pro Slot, entferne unnötige Locks und setze realistische Timeouts. Sicherheit halte ich hoch, justiere Regeln gegen Fehlalarme und sammele Beweise in Logs. Mit diesem Vorgehen bleiben HTTP Requests verlässlich erreichbar – selbst dann, wenn Traffic sprunghaft steigt und jede Sekunde zählt.

Aktuelle Artikel