Med fokus på Tidsgräns för HTTP Keep-Alive Jag visar dig hur du ställer in tomgångstider så att anslutningar återanvänds utan att blockera trådar. Jag förklarar specifika värden, visar typiska fallgropar och tillhandahåller beprövade och testade konfigurationer för nginx, Apache och operativsystemet.
Centrala punkter
- Balans: För korta ökar handskakningar, för långa blockerar trådar.
- VärdenOftast 5-15 s och 100-500 förfrågningar per anslutning.
- SamordningKoordinera timeouts för klienter, LB och brandväggar.
- Särskilda fallWebSockets, SSE, Long Polling separat.
- Övervakning: Övervaka öppna socklar, FD:er och latenser.
Kort förklaring av HTTP Keep-Alive
Jag har TCP-anslutningar med Keep-Alive öppna så att flera förfrågningar använder samma linje. Detta sparar mig upprepade TCP- och TLS-handskakningar och minskar CPU-overhead märkbart. Detta är särskilt fördelaktigt för många små filer, t.ex. ikoner, JSON eller CSS. Varje ny anslutning som undviks minskar antalet kontextbyten och avlastar kärnans rutiner. I benchmarks med en hög andel GET minskas den totala varaktigheten avsevärt eftersom färre SYN/ACK-paket genereras och mer beräkningstid flyter in i applikationslogiken.
Jag mäter snabbt effekten: den glidande genomsnittliga latensen blir jämnare och antalet nya TCP-anslutningar per sekund sjunker. Jag uppnår inte detta genom magi, utan genom att Återanvändning av anslutning och rimliga gränser. Det är fortfarande viktigt att Keep-Alive inte ersätter snabb rendering eller cachelagring. Det förkortar väntetiderna vid nätverksgränsen, medan själva appen måste fortsätta att svara effektivt. Båda tillsammans ökar Prestanda märkbart.
Förståelse för rätt timeout
Timeout definierar hur länge en inaktiv anslutning förblir öppen innan servern stänger den. stänger. Om jag ställer in den för kort öppnar klienterna ständigt nya TCP-anslutningar, vilket Overhead höjs. Om jag ställer in den för länge parkerar oanvända anslutningar värdefulla arbetare eller trådar. Tricket är att hitta en balans mellan återanvändning och resursförbrukning. Jag testar praktiskt: först ställer jag in den grovt, sedan finjusterar jag den med belastningstester.
Jag är också uppmärksam på förhållandet mellan svarstider och lediga fönster. Om den typiska användarinteraktionen mellan två klick är 2-4 sekunder, täcker en timeout på 5-15 sekunder vanligtvis det verkliga mönstret. Korta API-anrop kan lätt tolerera 5-10 sekunder, mediearbetsbelastningar 10-15 sekunder. Det är viktigt att jag inte överdriver: alltför långa timeouts leder sällan till mer Genomströmning, men leder ofta till blockerade Resurser. Jag kan snabbt känna igen detta på det ökande antalet öppna uttag och höga FD-siffror.
Separera timeout-typer på ett snyggt sätt
Jag gör en strikt åtskillnad mellan Tidsgräns för inaktivitet (Keep-Alive), Tidsgräns för läsning/header (hur länge servern väntar på inkommande förfrågningar) och Timeout för sändning/skrivning (hur länge sändning mot kunden tolereras). Dessa kategorier fyller olika uppgifter:
- Tidsgräns för tomgång: Styr återanvändningen och parkeringstiden för inaktiva anslutningar.
- Tidsgräns för läsning/header: Skyddar mot långsamma klienter (långsamma loris) och halvt skickade headers.
- Timeout för sändning/skrivning: Förhindrar att servern väntar i all oändlighet på en långsam mottagning hos klienten.
På nginx Jag använder medvetet header_timeout/read_timeout och send_timeout per kontext (http/server/location) utöver keepalive_timeout. Sedan nyare versioner ställer jag valfritt in keepalive_tid, för att begränsa den maximala livslängden för en anslutning, även om den förblir aktiv. I Apache Jag använder också RequestReadTimeout (mod_reqtimeout) och kontrollera Tidsgräns (global) separat från KeepAliveTimeout. Denna uppdelning är en viktig byggsten mot att binda upp resurser utan någon verklig nytta.
Rekommenderade värden i praktiken
För produktiva miljöer ställer jag in en timeout för keep-alive på 5-15 sekunder och 100-500 förfrågningar per anslutning. Det här intervallet ger bra återanvändning av anslutningar och håller antalet vilande anslutningar nere. På nginx Jag använder keepalive_timeout 10s som startvärde och keepalive_requests 200. Om det är mycket trafik ökar jag det måttligt om jag ser för många nya TCP-anslutningar. Om trafiken är gles sänker jag den igen för att förhindra en översvämning av oanvänd trafik.
De som går djupare kommer att dra nytta av en tydlig tuningprocess med mätpunkter. Därför har jag sammanfattat mina riktlinjer i en praktisk guide som beskriver vägen från mätning till konfiguration och kontroll. För en snabb start hänvisar jag dig till mina steg i Keep-Alive-inställning. Hur man kontrollerar Återanvändning och begränsningar och undvika överraskningar. Det som räknas i slutändan är låg latens med stabil Genomströmning.
Risker med långa timeouts
En lång timeout gör att anslutningarna blir konstgjorda öppna och blockerar arbetare även om ingen begäran följer. Detta gör att uttagen sväller och driver upp filbeskrivningsnummer. Om processen når sina gränser ser jag avvisande acceptfel eller köer när jag upprättar en anslutning. Minnet växer, garbage collectors eller allocators kostar extra tid och latensen ökar. I händelse av ett fel skickar klienter sedan till socklar som redan är stängda och får kryptiska Fel.
Jag undviker detta genom att sätta måttliga värden och kontrollera regelbundna mätvärden. Om antalet inaktiva anslutningar ökar för mycket under låg belastning sänker jag timeouten. Om jag ser många nya anslutningar per sekund under trafiktoppar ökar jag den försiktigt i små steg. Det är så här jag håller Kapacitet användbara och förhindrar döda anslutningar. Resultatet är ett smidigare system med färre Tips i kurvorna.
Konfiguration: nginx, Apache och OS-lager
Jag börjar på webbservernivå och ställer in timeout och gränser. På nginx Jag ställer in keepalive_timeout 5-15s och keepalive_requests 100-500. I Apache med event-MPM kombinerar jag KeepAlive On, KeepAliveTimeout 5-15 och MaxKeepAliveRequests 100-500. Sedan kalibrerar jag worker- eller trådpooler enligt den förväntade belastningen. Detta förhindrar att inaktiva keep-alives blir produktiva. Spelautomater binda.
Jag ökar gränserna och köerna på operativsystemnivå. Jag sätter ulimit -n till minst 100 000, justerar net.core.somaxconn och tcp_max_syn_backlog och kontrollerar TIME_WAIT-hanteringen. Detta säkerställer att kärnan och processen har tillräckligt med Resurser tillhandahålla. Slutligen verifierar jag vägarna från NIC via IRQ-balansering till appen. Detta gör att jag kan upptäcka flaskhalsar i god tid och hålla Fördröjning låg.
| Komponent | Direktiv/Inställning | Rekommendation | Ledtråd |
|---|---|---|---|
| nginx | keepalive_timeout | 5–15 s | Kortare med liten trafik, längre med många små förfrågningar |
| nginx | keepalive_requests | 100–500 | Återvinner föreningar och minskar Läckage |
| Apache (evenemang) | KeepAliveTimeout | 5–15 s | Event-MPM hanterar tomgång mer effektivt än prefork |
| Operativsystem | ulimit -n | ≥ 100.000 | Fler öppna FD:er för många Socklar |
| Operativsystem | net.core.somaxconn | Ökning | Färre avvisade anslutningar under Toppbelastning |
Omvänd proxy och återanvändning uppströms
Jag tänker alltid keep-alive end-to-end. Bakom edge-servern finns ofta en kedja av reverse proxy → app-servrar. För nginx aktiverar jag min egen Keep Alive Pools (uppströms keepalive, keepalive_requests, keepalive_timeout), ställ in proxy_http_version 1.1 och ta bort „Connection: close“. Detta sparar mig också intern handskakningar och avlasta app-backends (Node.js, Java, PHP-FPM). I Apache med mod_proxy behåller jag också beständiga anslutningar till backend-servrar och begränsar dem per destination så att en hotspot inte monopoliserar poolerna.
Jag mäter separat: Återanvändningsgrad Client→Edge och Edge→Backend. Om jag ser god återanvändning vid kanten, men många nya anslutningar till backend, ökar jag selektivt poolerna uppströms. Detta gör att jag kan skala utan att globalt öka timeouts för frontend.
Arbetare, trådar och OS-gränser
Jag dimensionerar inte medarbetare, händelser och trådar efter önskade värden, utan efter lastprofil. För att göra detta övervakar jag aktiva förfrågningar, lediga arbetare, användning av händelseslingor och kontextbyten. Om trådar parkeras i inaktivitetsläge sänker jag timeouten eller maxgränsen för inaktivitet per tråd. Om jag ser 100 procent CPU hela tiden kontrollerar jag acceptköer, IRQ-distribution och nätverksstack. Små korrigeringar av FD-gränser och backlogs gör ofta stor skillnad. Effekter.
Jag planerar mitt utrymme på ett realistiskt sätt. En 20-30-procentig reserv i trådar och FD:er ger säkerhet för toppar. Om jag överdriver förlorar jag cacher och slöseriet ökar. Om jag underdriver hamnar förfrågningar i köer eller förfaller. Den rätta skärningspunkten mellan Kapacitet och effektivitet håller latenstiderna låga och skyddar Stabilitet.
Samordna timeouts för klienter, lastbalanserare och brandväggar
Jag sätter tidsgränser längs hela vägen så att det inte blir några återvändsgränder. Anslutningar skapas. Klienter stänger helst minimalt tidigare än servern. Lastbalanseraren får inte skära av kortare, annars kommer jag att se oväntade återställningar. Jag inkluderar tomgångsvärden för NAT och brandväggar så att anslutningar inte går förlorade i nätverksvägen. försvinna. Denna inställning förhindrar retransmissioner och jämnar ut belastningskurvorna.
Jag håller kedjan begriplig med tydliga diagram: Klient → LB → webbserver → app. Jag dokumenterar tidsfrister för inaktivitet, tidsfrister för läsning/skrivning och strategier för omprövning för varje länk. Om jag ändrar ett värde kontrollerar jag grannarna. På så sätt förblir vägen konsekvent och jag får reproducerbara mätresultat. Denna disciplin sparar tid i Felsökning och ökar tillförlitlighet.
Säkerhet: Skydd mot långsamma loris och missbruk i onödan
Öppna timeouts som är för generösa Attackera ytor. Jag sätter därför gränser som tillåter legitim återanvändning men gör det svårare att hålla dem öppna på ett illvilligt sätt. I nginx hjälper header och read_timeout, request_headers_size-gränser och en hård övre gräns för keepalive_requests. I Apache använder jag mod_reqtimeout och begränsar parallella anslutningar per IP. Hastighetsgränser och limit_conn i nginx skyddar också mot översvämningar av många lediga socklar. För långkörande slutpunkter separerar jag dedikerade pooler så att attacker på strömmar inte binder vanliga API-arbetare.
Specialfall: Long Polling, SSE och WebSockets
Långa strömmar kolliderar med korta Tidsfrister och behöver sina egna regler. Jag separerar dessa slutpunkter tekniskt från klassiska API- och tillgångsvägar. För SSE och WebSockets ställer jag in högre timeouts, dedikerade arbetspooler och hårda gränser per IP. Jag håller anslutningen vid liv med hjärtslag eller ping/pong och känner snabbt igen avbrott. På så sätt blockerar inte strömmar trådar för vanliga Korta förfrågningar.
Jag begränsar samtidiga anslutningar och mäter aktivt. Gränser som är för höga förbrukar FD och RAM. Gränser som är för snäva stänger av legitima användare. Jag hittar den rätta punkten med rena mätvärden för öppna, inaktiva, aktiva och avbrutna anslutningar. Den här separationen sparar mig globala Ökar timeouts och skyddar den Kapacitet.
HTTP/2, multiplexering och keep-alive
HTTP/2 multiplexerar flera strömmar via en Anslutning, men är fortfarande beroende av timeouts. Jag håller inaktivitetsfönstret måttligt eftersom sessioner också kan parkeras under HTTP/2. Höga keepalive_requests är mindre viktiga här, men återvinning är fortfarande användbart. Head-of-line-blockering flyttas till ramnivå, så jag fortsätter att mäta latens per Ström. Om du vill jämföra mer i detalj hittar du bakgrundsinformation på HTTP/2-multiplexering.
Under HTTP/2 är jag särskilt uppmärksam på antalet aktiva strömmar per anslutning. För många parallella strömmar kan överbelasta apptrådar. Jag sänker då gränserna eller ökar antalet serverarbetare. Samma sak gäller här: mät, justera, mät igen. Detta håller Svarstider sällsynta och välbevarade Resurser.
TLS, återupptagande av session och HTTP/3/QUIC
TLS-handskakningar är dyra. Jag använder Återupptagande av session (biljetter/ID:n) och OCSP-häftning så att återanslutningarna går snabbare om en anslutning bryts. Under HTTP/3 tar QUIC över transportlagret: Här är QUIC idle timeout som liknar Keep-Alive, men på UDP-basis. Även här håller jag fönstren måttliga och mäter retransmits, eftersom paketförluster har en annan effekt än med TCP. För blandade miljöer (H1/H2/H3) väljer jag standardiserade referensvärden och gör finjusteringar för varje protokoll.
Övervakning, mätvärden och belastningstester
Jag litar mer på mätdata än på magkänsla och börjar med tydliga KPI:er. Viktigt är: öppna uttag, FD-användning, nya anslutningar/s, latenser (P50/P90/P99), felfrekvenser och retransmissioner. Jag kör realistiska belastningsprofiler: Uppvärmning, platå, nedrampning. Sedan jämför jag kurvorna före och efter ändringar av timeouten. En titt på Serverköer hjälper till att tydligt tolka väntetider.
Jag dokumenterar varje justering med en tidsstämpel och mätvärden. På så sätt kan jag bevara historiken och känna igen samband. Jag tar negativa effekter på allvar och återställer dem snabbt. Små, begripliga steg sparar mycket tid. Det som räknas i slutändan är en stabil Fördröjning och låg Felprocent under belastning.
Mätmetoder och verktyg i praktiken
- Snabbtester: Jag använder verktyg som wrk, ab eller vegeta för att kontrollera återanvändningskvoter (-H-anslutning: keep-alive vs. close), anslutningar/s och latenspercentiler.
- Systemvy: ss/netstat visar status (ESTABLISHED, TIME_WAIT), lsof -p FD-förbrukning, dmesg/syslog indikation på dropp.
- Mätvärden för webbserver: nginx stub_status/VTS och Apache mod_status ger aktiv/ledig/väntande och förfrågningar/s. Från detta kan jag känna igen lediga toppar eller flaskhalsar för arbetare.
- Spår: Jag använder distribuerad spårning för att övervaka om väntetider uppstår vid nätverksgränsen eller i appen.
Konfigurera steg för steg
Först fastställer jag det verkliga användningsmönstret: hur många förfrågningar per session, vilka Intervaller mellan klick, hur stora är svaren. Sedan ställer jag in en första profil: timeout 10 s, keepalive_requests 200, måttligt antal arbetare. Sedan utför jag belastningstester med representativa data. Jag utvärderar antalet nya anslutningar per sekund och FD-användningen. Jag justerar sedan Värden i steg om 2-3 sekunder.
Jag upprepar cykeln tills latenserna förblir stabila under belastning och FD-topparna inte når gränsen. Vid hög belastning ökar jag timeouten endast om jag tydligt ser att det finns färre nya anslutningar och att det fortfarande finns lediga arbetare. Vid låg användning minskar jag timeouten för att undvika tomgångskörning. I specialfall som SSE ställer jag in dedikerade serverblock med högre gränser. Den här vägen leder till en motståndskraftig Inställning utan priskartong.
Kubernetes, containrar och automatisk skalning
I containermiljöer använder jag conntrack-gränser, pod FD-gränser och node backlogs. Jag säkerställer konsekventa timeouts för inaktivitet mellan Ingress, service mesh/proxy och app. För automatisk skalning är jag uppmärksam på AvloppstiderNär pods avslutas bör de avvisa nya anslutningar via „Connection: close“ och betjäna befintliga anslutningar på ett snyggt sätt. Keep alive-värden som är för långa drar ut på tiden i onödan, medan de som är för korta genererar handskakningsstormar vid utskalning.
Graceful shutdown och rullande driftsättningar
Jag planerar också att stänga av. Innan en utrullning minskar jag gradvis Keep-Alive eller skickar riktade Anslutning: stäng på Responses så att klienterna inte öppnar nya oanvända anslutningar. I nginx är en timeout för avstängning av arbetare för pågående förfrågningar. I Apache använder jag graciösa mekanismer och håller ett öga på MaxConnectionsPerChild/Worker så att återvinning sker automatiskt över tid. Detta håller distributionerna smidiga utan att hårt begränsa öppna socklar.
OS-tuning: portar, timeouts, kärnparametrar
- kortlivade hamnar: Välj ett brett ip_local_port_range så att kortlivade anslutningar inte hamnar i en bristsituation.
- TIME_WAIT: Jag håller koll på TW-toppar. Moderna stackar hanterar detta bra; jag undviker tveksamma tweaks (tw_recycle).
- tcp_keepalive_tid: Jag blandar inte ihop det med HTTP Keep-Alive. Det är en kärnmekanism för att känna igen döda peers - användbart bakom NAT, men inte en ersättning för HTTP:s idle-fönster.
- Eftersläpningar och buffertar: dimensionera somaxconn, tcp_max_syn_backlog och rmem/wmem på ett förnuftigt sätt för att inte strypas under belastning.
Checklista för felsökning
- Många nya anslutningar/s trots keep-alive: Timeout för kort eller klienter/LB stängdes av tidigare.
- Höga tomgångssiffror och full FD: För lång timeout eller för stora arbetspooler för trafikmönstret.
- RST/Timeout-fel för längre sessioner: NAT/brandväggsledighet för kort i vägen, asymmetri mellan länkar.
- Långa väntetider (P99): Kontrollera timeouts för sändning/läsning, långsamma klienter eller överfyllda backlogs.
- Backends överbelastade trots låg kantbelastning: Buren uppströms saknas eller är för liten.
Övningsprofiler och startvärden
- API-first (korta anrop): Keep-Alive 5-10 s, keepalive_requests 200-300, tight header/read timeouts.
- E-handel (blandad): 8-12 s, 200-400, något mer generöst för produktbilder och cacheträffar.
- Tillgångar/CDN-liknande (många små filer): 10-15 s, 300-500, starka uppströmspooler och höga FD-gränser.
- Intranät/låg belastning: 5-8 s, 100-200, så att tomgång inte dominerar.
Kortfattat sammanfattat
Jag ställer in HTTP keep-alive timeout så att anslutningar återanvänds utan att blockera trådar. I praktiken ger 5-15 sekunder och 100-500 förfrågningar per anslutning mycket bra resultat. Jag samordnar timeouts för klienter, lastbalanserare och brandväggar, separerar långvariga anslutningar som WebSockets och reglerar OS-gränser. Med noggrann övervakning, realistiska belastningstester och små steg uppnår jag låga Fördröjningar och hög Genomströmning. De som upprätthåller denna disciplin får ut mätbar prestanda av befintlig hårdvara.


