HTTP-anmodninger kan blokere, selv om CPU, RAM og båndbredde ser ud til at være åbne, fordi usynlige grænser, filtre og køer træder i kraft i hele kæden. Jeg forklarer, hvor Grænser hvordan de fungerer, og hvilke indstillinger jeg sætter, så forespørgsler kører problemfrit igen.
Centrale punkter
Før jeg går i detaljer, vil jeg opsummere de vigtigste årsager og nævne, hvad jeg ser på først. Disse punkter dækker de typiske flaskehalse, der fører til overbelastning på trods af frie ressourcer. Jeg har med vilje holdt listen kompakt, så du straks kan tjekke udgangspunktet. Det vigtigste er, at hvert lag har sine egne regler, som gælder uafhængigt af CPU og RAM. Hvis du kender disse regler, kan du hurtigt løse mange „uforklarlige“ ventetider.
- Grænser for arbejdereFor få processer/tråde blokerer for nye forbindelser på trods af ledig CPU.
- SikkerhedslagWAF/webfiltre blokerer mønstre, metoder eller klienter, ofte uden høj belastning.
- SamtidighedPHP-FPM, database og proxyer begrænser antallet af samtidige sessioner.
- Keep-Alive/TimeoutsLange forbindelser optager tid, og forespørgsler ender i kø.
- Klient-filterBrowserudvidelser stopper anmodninger, før de når frem til serveren.
Disse nøglepunkter er ofte nok til at kontrollere adfærd på en målrettet måde. I det følgende vil jeg vise dig, hvordan jeg udleder specifikke foranstaltninger fra dette og Blokeringer rent.
Hvorfor HTTP-anmodninger blokerer trods ledige ressourcer
En anmodning passerer gennem flere lag: Klient, netværk, filter, webserver, runtime-miljø og database. Hvert lag har sin egen Grænser som træder i kraft uanset CPU, RAM eller båndbredde. Hvis worker-slots er optaget, eller regler er aktive, venter anmodningen i en kø eller bliver straks annulleret. Denne ventetid vises ofte slet ikke i klassiske ressourcediagrammer. Det er netop det, der fører til den misforståelse, at serveren er „tom“, selv om der ikke besvares anmodninger.
Sikkerhedslag: WAF, filtre og udbyderregler
Mange blokeringer opstår, før applikationen overhovedet kører. Firewalls til webapplikationer, IDS/IPS og filtre på udbydersiden genkender mønstre og gør dem langsommere eller blokerer dem [1][5][9]. Mistænkelige parametre, gamle protokoller eller kombinationer af metoder er nok til at forårsage en Lås at antænde. Fra operatørens synspunkt ser det ud som en serverfejl, men beslutningen træffes „upstream“. Jeg tjekker derfor WAF-logfilerne og noterer request-ID, IP, tid og statuskode. Med disse data kan reglen identificeres og justeres på en målrettet måde uden at gå på kompromis med sikkerheden.
Klientsiden: browserudvidelser og lokale blokeringer
Ikke alle anmodninger når frem til serveren. Adblockere, adgangskodeadministratorer og scriptblokkere stopper allerede URL'er i browseren; DevTools viser derefter „Anmodninger til serveren er blevet blokeret af en udvidelse“ [3][7]. Jeg tester i et privat vindue, deaktiverer udvidelser og kontrollerer, om Anmodning overhovedet blev sendt. Det hjælper også med at styre prioriteterne i frontend, for eksempel med en ren Prioritering af anmodninger for kritiske aktiver. Det forhindrer ikke-kritiske tredjepartsopkald i at forsinke vigtige ruter.
Forståelse af metode og routing: 405, 403, 429
En 405 „Method Not Allowed“ viser tydeligt, at serveren anerkender ressourcen, men ikke tillader den anvendte metode [5]. På samme måde indikerer 403 filtre eller rettigheder og 429 aktiv hastighedsbegrænsning. I logfiler kan jeg hurtigt se, om en global regel tillader metoder som f.eks. PUT eller DELETE, eller om et endpoint aldrig er blevet implementeret. Derefter justerer jeg routingen, controlleren eller WAF-reglen. På denne måde opløses den formodede „blokering“ i en ren korrektion af metoder og stier.
Webserver-arkitektur og arbejdsbegrænsninger
Apache, NGINX, LiteSpeed og OpenLiteSpeed håndterer forbindelser forskelligt [4]. De afgørende faktorer er antallet af arbejdsprocesser, tråde og hvordan keep-alive-sockets optager slots. Hvis alle workers er optaget af lange forbindelser, flyttes nye forespørgsler til en Kø, selvom CPU'en og RAM'en ser ud til at være fri. Jeg analyserer derfor forbindelsestilstande og justerer workers, backlogs og keep-alive-tider. Baggrundsviden om køer hjælper, for eksempel med emnet Serverkø og ventetid.
| lag | Relevant grænse | Typisk symptom | Diagnostisk note |
|---|---|---|---|
| Webserver | Antal arbejdere/tråde | Køer, 503 under belastning | Statusmoduler, tjekker forbindelsesstatusser |
| PHP-FPM/FastCGI | max_børn / pm | Hængende forespørgsler, høj time-to-first-byte | FPM-logfiler, langsom log, antal processer |
| Database | max_forbindelser | Fejl „For mange forbindelser“ | VIS PROCESSLISTE, forbindelsestoppe |
| WAF/Filter | Underskrifter, metoder | 403/405, ødelagte formularindlæg | WAF-logfiler, regel-hit-id'er |
| Load Balancer | Begrænsning pr. backend-conn | Inkonsekvente svartider | LB-statistik, Backend-sundhed |
Samtidighed i PHP-FPM, database og proxyer
Samtidig behandling kommer ofte først i runtime-miljøet. Hvis alle PHP FPM-medarbejdere har travlt, er der ikke plads til nye scripts; anmodningerne venter, selv om CPU virker næsten ikke. Situationen er den samme for databaser med max_connections eller for proxyer med forbindelsesgrænser pr. backend. Jeg optimerer først varigheden af de enkelte anmodninger, før jeg øger grænserne. På den måde forkorter jeg dokumenttiden pr. slot og reducerer sandsynligheden for, at køerne vokser.
Langsomme backends og låsning af PHP-sessioner
Lange databaseforespørgsler, eksterne API'er eller fil-I/O binder medarbejderne betydeligt længere. Sessionslåsning kan også gøre hele kæder langsommere, f.eks. WordPress-logins eller indkøbsvogne. Jeg tjekker, om parallelle forespørgsler til det samme sessions-ID kører efter hinanden i stedet for samtidig. Hvis det er tilfældet, bruger jeg målrettet oplåsning, reducerer kritiske skriveadgange og følger de velafprøvede instruktioner på Låsning af PHP-sessioner. Det giver mig mulighed for at frigøre slots hurtigere og reducere Ventetider Bemærkelsesværdigt.
Timeouts, keep-alive og forbindelsesstrategier
Keep-alive-tider, der er for lange, binder ressourcer, mens de, der er for korte, genererer handshakes og ventetid. Jeg vælger værdier, der matcher trafikprofilen, og sætter grænser for header-, body- og backend-timeouts. Det er vigtigt at indstille timeouts ikke kun på Webserver men standardiseret i hele kæden: proxy, app, database. Derudover forhindrer jeg inaktiv blokering gennem finere HTTP/2/HTTP/3-indstillinger og prioritering. Dette holder slots tilgængelige, uden at klienter konstant skal oprette forbindelse igen.
Hosting-modeller: Delt, VPS, Dedikeret
Delt hosting indstiller tidlige filtre og hårde kvoter, så platformen forbliver fair [1]. På VPS isolerer udbyderne CPU og RAM, men opretholder grænser for I/O, netværk eller sikkerhed; forskelle i ydeevne og overvågning er tydelige [10]. På dedikerede servere har jeg det fulde ansvar for webserver-, database- og WAF-konfigurationen. Sammenligninger viser, at moderne stakke med HTTP/3, NVMe og DDoS-beskyttelse giver klare fordele [2][6][11][8]. De, der har brug for høj parallelitet, nyder godt af klart dokumenterede Grænser og støtte, som hjælper med reglenheder.
Systematisk analyse: trin for trin
Jeg starter ved kilden: Sender DevTools virkelig anmodningen, eller er det en udvidelse [3][7], der blokerer den? Derefter ser jeg på statuskoder: 403/405/429/503 giver stærke indikationer på filtre, metoder eller kapacitet [5]. Samtidig tjekker jeg logfiler fra webserveren, appen og WAF for at finde mønstre og tilbagevendende signaturer [1][9]. Derefter tjekker jeg antallet af arbejdere, FPM-parametre, keep-alive og databaseforbindelser og øger grænserne på testbasis med målepunkter før og efter. Til sidst simulerer jeg belastningen, observerer flaskehalse i realtid og kontrollerer, at Køer krympe.
Bedste praksis mod blokader
Jeg formulerer mål for samtidighed pr. lag og sætter grænser, så belastningstoppe dæmpes. Webserveren skal matche trafikmønsteret; benchmarks hjælper med udvælgelsen og konfigurationen [4]. Jeg optimerer først backends logisk: hurtigere forespørgsler, kortere transaktioner, færre serielle sektioner. Jeg holder sikkerhedsreglerne strenge nok mod angreb, men med undtagelser for legitime angreb. Prøve. Overvågningen slutter ikke med CPU/RAM: Jeg ser på forbindelser, køer, svartider og fejlkoder, så flaskehalse forbliver synlige [6][11].
Øvelsesnoter: hosting med blokering af anmodninger
I delte miljøer ender blokader ofte før det faktiske webhotel; support har derefter brug for specifikke forespørgselsdata for at justere reglerne [1]. På VPS skalerer jeg gradvist: flere arbejdere, mere passende keep-alive-værdier og tættere overvågning af databasen [10]. På min egen hardware beslutter jeg mig for belastningsbalancering, WAF-regler og grænser pr. backend. Projekter med meget parallel adgang nyder godt af en ren HTTP/2/HTTP/3-konfiguration og klare reserver til Tips. Hvis du forventer vækst, skal du planlægge skiftet til kraftigere tariffer tidligt og spare en masse indstillingsarbejde senere [2][6][10][11].
Netværks- og kernelgrænser: backlog, porte og deskriptorer
Ud over webserveren og appen begrænser kernen, hvor mange forbindelser der kan ankomme, etableres og håndteres på samme tid. Jeg tjekker først Liste over efterslæbSelv om webserveren har mange arbejdere, kan acceptkøen være kort. Samspillet mellem applikationen (listen backlog), kernen (somaxconn) og SYN backlog (tcp_max_syn_backlog) afgør, om forbindelserne forbliver i køen eller bliver kasseret. Symptomerne er stigende forbindelsestider og retransmissioner - med lav CPU-udnyttelse. Jeg sammenligner værdierne og måler den faktiske udnyttelse af køerne for at undgå udfald.
En anden klassiker er conntrack-bord til NAT/firewall-opsætninger. Hvis den er fuld, forsvinder forbindelserne „sporløst“; programmet ser aldrig en anmodning. Jeg genkender det på beskeder i systemloggen og pludselige timeouts under spidsbelastninger. Modforanstaltningerne er: passende tabelstørrelse, realistiske idle timeouts for protokoller, færre unødvendige NAT-stier og effektive keep-alives, der genbruger forbindelser på en fornuftig måde.
Jeg tjekker også antallet af åbne Filbeskrivelser (ulimit -n). Hvis mange samtidige sockets og filer rammer restriktive grænser, fejler Accept („for mange åbne filer“), og nye anmodninger hober sig op foran den. Løsningen er normalt triviel: Indstil nofile-grænserne for webserveren, proxyen og databasen til et sundt niveau - vedvarende, ikke kun interaktivt.
I stærkt parallelle opsætninger observerer jeg Kortvarigt portområde og TIME_WAIT-tilstande. Især bag NAT-gateways bliver de tilgængelige kildeporte opbrugt, når korte forbindelser etableres i massevis. Derfor benytter jeg mig af genbrug af forbindelser (keep-alive, HTTP/2/3), reducerer unødvendige kortvarige forbindelser og indstiller TIME_WAIT-håndteringen omhyggeligt uden at risikere stabiliteten. Resultatet: mindre portudmattelse og mere stabile forbindelsestider under belastning.
På netværkskortet tjekker jeg kø-længder, offloading-indstillinger og IRQ-fordeling. Ujævnt fordelte afbrydelser eller overbelastede køer genererer latenstidstoppe, som ikke kan ses i programlogfiler. Med afbalanceret IRQ-balancering og fornuftige Qdisc-indstillinger (nøgleord Bufferbloat) Jeg reducerer ventetiden uden at begrænse båndbredden.
HTTP/2 og HTTP/3: Brug multiplexing korrekt
Multiplexing løser mange problemer, men medfører også nye begrænsninger: Maksimalt antal strømme, flow control window og idle timeouts gælder pr. forbindelse. Hvis værdien for samtidige streams er for lav, „hænger“ nye forespørgsler, selv om TCP- eller QUIC-forbindelsen er etableret. Jeg tjekker derfor, hvor mange kritiske ressourcer, der skal indlæses parallelt, og justerer omhyggeligt stream-grænserne. Samtidig er jeg opmærksom på rimelige Kontrol af flow-vindue, så store svar ikke bliver neddroslet.
HTTP/2-multiplexer over TCP kan lide af head-of-line-blokering i tilfælde af pakketab; HTTP/3 på QUIC undgår dette, men kræver rene TLS/ALPN-indstillinger og stabile stihåndteringsregler. Jeg tester begge stier og vælger de protokoller, der matcher trafikprofilen. Vigtigt: Stol ikke blindt på prioritering - browsere og servere fortolker det forskelligt. Jeg fokuserer på kritiske ruter og tjekker, om prioriteringerne rent faktisk fungerer, og om pladserne ikke optages af langvarige sekundære strømme.
CORS, preflights og header/body-grænser
Ikke alle 4xx-fejl kommer fra serveren. CORS-overtrædelser opstår i browseren og vises i konsollen, ikke i adgangsloggen. Jeg kontrollerer, om preflight-anmodninger (OPTIONS) besvares korrekt, og om WAF/proxies tillader denne metode. Hvis overskrifter som Access-Control-Allow-Methods/-Headers mangler, „blokerer“ browseren svaret - uden nogen serverbelastning.
Endnu en flaskehals: Header- og cookie-størrelser. Overgroede cookies, mange Vary-headere eller store referer-linjer fører til 431-fejl eller lydløse udfald på grund af bufferbegrænsninger. Jeg begrænser cookie-ballast, konsoliderer headers og indstiller bufferstørrelser konsekvent langs kæden. Ved uploads er jeg opmærksom på body-grænser, 100-continue-håndtering og konsekvent Chunked-kodning-Understøttelse af alle proxyer. Hvis body- og uploadgrænserne ikke stemmer overens, venter klienter på en frigivelse, der aldrig kommer - anmodninger ser ud til at „hænge“.
DNS og TLS: Håndtryk som skjult latenstid
DNS-opløsning og TLS-forhandling er ofte blinde pletter. Flere CNAME-kæder, langsomme resolvere eller IPv6/IPv4-mismatch forlænger starttiden uden at bruge CPU. Jeg reducerer unødvendige DNS-spring, indstiller fornuftige TTL'er og sikrer hurtige resolver-stier. På TLS-siden tjekker jeg certifikatkæder, aktiverede cipher suites, OCSP-hæftning og genoptagelse af sessioner. Et rent ALPN-handshake forhindrer nedgraderinger til HTTP/1.1, som lægger et større pres på keep-alive-slots. Resultat: kortere time-to-first-byte og mere stabil parallelitet, især på mobilnetværk.
CDN/Edge: Caching, hastighedsgrænser og IP-omdømme
Mellem klient og oprindelse beslutter CDN'er, reverse proxyer og DDoS-beskyttelsessystemer sig for Kulvert og drosler ned. Jeg tjekker, om kritiske ruter er cached korrekt (stale-while-revalidate, stale-if-error), og om negative caches holder på fejl længere end nødvendigt. Hastighedsgrænser, bot-styring og IP-omdømme kan dæmpe legitim trafik, især med delte netværk eller tung API-adgang. Jeg segmenterer trafik (f.eks. API vs. aktiver), definerer klare cachenøgler og deaktiverer regler selektivt for betroede klienter. Det aflaster Origin og forhindrer CDN-køer i at vokse, mens serveren ser ud til at være „underudnyttet“.
Containere og orkestrering: cgroups, Ingress og conntrack
I beholdere gælder cgroup-grænser for CPU, RAM, pids og filer. En for stram CPU-kvote fører til throttling: Processer venter på CPU-tid, selv om værten er ledig. Jeg tjekker kvoter og sørger for, at ingress/proxy-pods har nok filbeskrivelser og buffere. I Kubernetes tjekker jeg ingress-timeouts, readiness/liveness-probes og serviceimplementeringer (IPVS), fordi defekte probes eller timeouts skaber zigzag-latency og unødvendige genstarter.
En ofte overset flaskehals er NAT/conntrack-kapacitet pr. node. Mange kortvarige forbindelser (f.eks. udgang til eksterne API'er) fylder conntrack-tabellen, og derefter „forsvinder“ anmodningerne i netværket. Jeg skalerer tabellen, indstiller realistiske timeouts og bundter eksterne opkald, så der oprettes færre nye forbindelser. Jeg planlægger PodDisruptionBudgets, rullende opdateringer og HPA-skalering på en sådan måde, at der ikke trækkes kapacitet fra planlæggeren i spidsbelastningsperioder - ellers dannes der køer, selv om appen teoretisk set ville have nok arbejdere.
Observerbarhed: korrelation, sporing og meningsfulde målinger
For at finde blokeringer hurtigt har jeg brug for Kontinuerlig korrelation. Jeg tildeler request-id'er (f.eks. traceparent) til edge, webserver, app og database og skriver dem i logfilerne. Det giver mig mulighed for at se, om en anmodning fejler i WAF'en, venter på webserveren, sidder fast i FPM-køen eller er blokeret i databasen. Jeg arbejder med Histogrammer i stedet for rene gennemsnitsværdier og overvåger P95/P99-latency, åbne forbindelser, acceptkø, FPM-kølængde, aktive DB-sessioner og backend-fejlkoder. Jeg bruger også syntetiske kontroller til klart at adskille effekter på klientsiden fra effekter på serversiden.
Til anomalier bruger jeg en DrilldownProceduren: først edge/WAF-logfiler, så load balancer, så webserveradgang/fejl, så app- og FPM-logfiler og til sidst DB- og systemlogfiler. Denne sti viser mig præcis, hvor tiden går tabt, og ved hvilken grænse anmodningen stopper. Med målrettede målinger pr. lag undgår jeg mavefornemmelser og reducerer drastisk tiden til den grundlæggende årsag.
Tuning-playbook og tjekliste
I praksis har jeg en kompakt drejebog, som jeg tilpasser til omgivelserne:
- Reproducerbarhed: Fastlæg scenarie (rute, metode, størrelse, klient), logtidsstempel og ID'er.
- Tjek lag for lagBrowser/udvidelser, CORS/Preflight, WAF-Hits, LB-Stats, Webserver-Status, FPM-Queue, DB-Active/Locks.
- Gør køer synligeAccept/SYN-backlog, FPM-lyttekø, proxy-backlog, DB-forbindelsespulje.
- Synkroniser grænserWorker/threads, somaxconn, nofile, max_connections, stream-grænser for H2/H3, body/header-grænser, timeouts.
- Reducer belægningstidenFremskynd forespørgsler, undgå sessionslåse, reducer I/O, komprimér svar og sæt dem i cache på en fornuftig måde.
- Harmoniser strategierKeep-Alive-varighed, HTTP/2/3-parametrisering, prioritering af kritiske ruter.
- Juster sikkerheden: Målrettet udelukkelse af WAF-regler i stedet for global svækkelse; logning med hit-id'er.
- SkaleringDefiner samtidighed pr. skift, kør belastningstest, mål reserver, øg kun grænserne efter optimering.
- TilbagefaldCircuit breaker til langsomme backends, retry policy med jitter, „stale-if-error“ til kritiske aktiver.
Kort opsummeret
Blokerede forespørgsler med ledig CPU og RAM skyldes som regel grænser, filtre og forbindelsesstrategier - ikke manglende ydeevne. Jeg tjekker først, hvor forespørgslen stopper: browser, WAF, webserver, runtime eller database. Derefter minimerer jeg belægningstiden pr. slot, fjerner unødvendige Låse og indstiller realistiske timeouts. Jeg holder sikkerheden høj, justerer regler mod falske alarmer og indsamler beviser i logfiler. Med denne tilgang forbliver HTTP-anmodninger pålideligt tilgængelige - selv når trafikken stiger, og hvert sekund tæller.


