Jag konfigurerar NGINX Upstream Keepalive så att den omvända proxyn upprättar färre anslutningar, ger lägre latens och på ett tillförlitligt sätt hanterar belastningstoppar. I samband med detta justerar jag Poolens storlek, tidsgränser och rubriker på ett målinriktat sätt så att anslutningar återanvänds och datavägen förblir slimmad.
Centrala punkter
- HTTP/1.1 tvinga fram och rensa Connection-rubriker
- keepalive dimensionera korrekt per arbetare
- Tidsfrister anpassa till backend-värden
- Förfrågningar/Anslutning begränsa och återvinna
- Övervakning för anslutningshastighet och fördröjning
Varför Upstream Keepalive drastiskt minskar anslutningsarbetet
Utan återanvändning öppnar NGINX en ny backend-anslutning för varje begäran, vilket medför extra handskakningar, fler CPU-cykler och ytterligare kärnresurser; det är just här som Keepalive Jag låter NGINX cacha redan upprättade, tillfälligt inaktiva socklar och använda dem för efterföljande förfrågningar, vilket märkbart minskar anslutningstiderna. Detta sänker antalet anslutningar per sekund, minskar toppar i backloggen och bromsar kontextbyten i operativsystemet. Särskilt vid TLS-anslutningar till backend sparar jag märkbart tid genom återanvända sessioner. På så sätt förblir svarskedjan stabil även vid hög genomströmning pålitlig och reagerar smidigt.
Grundprincipen och keepalive-direktivet i Upstream
Direktivet keepalive I upstream-blocket begränsas antalet inaktiva backend-anslutningar som cachelagras per arbetare. Denna gräns gäller inte globalt, utan strikt per arbetarprocess, vilket är anledningen till att jag alltid håller koll på antalet arbetare. När poolen är full stänger NGINX först den anslutning som varit oanvänd längst, så att det finns plats för nya socklar. För återanvändning kräver proxysidan HTTP/1.1 och en neutraliserad Connection-header. Utan dessa förutsättningar förblir poolen tom, trots att jag ställer in „keepalive“ i uppströmsinställningarna, vilket många administratörer inledningsvis överraskad.
upstream backend_pool {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
keepalive 32; # inaktiva anslutningar per arbetare
keepalive_requests 1000; # återanvändning efter N förfrågningar
keepalive_timeout 60s; # livslängd för inaktiva anslutningar
}
server {
listen 80;
location / {
proxy_pass http://backend_pool;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Obligatoriska direktiv i Location-blocket: HTTP/1.1 och kontroll av rubriker
Jag tvingar NGINX att använda HTTP/1.1 i proxysökvägen, eftersom Keepalive inte fungerar korrekt med HTTP/1.0 och anslutningarna avslutas i onödan; direktiven proxy_http_version 1.1 är därför obligatoriskt. Dessutom tar jag bort Connection-headern för vanliga förfrågningar, så att backenden inte får någon „close“-instruktion. För uppgraderingar som WebSockets anger jag specifikt „Connection: Upgrade“ via map, utan att det påverkar den normala återanvändningen. På så sätt förblir anslutningspolicyn konsekvent och fristående från klienthuvuden. Just denna lilla ändring förhindrar många svårfångade Felbilder.
location / {
proxy_pass http://backend_pool;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
map $http_upgrade $connection_upgrade {
default upgrade;
"" "";
}
Finjustering: Välj rätt värden för keepalive_requests och keepalive_timeout
Med två justeringsskruvar reglerar jag livslängden och förnyelsen av anslutningarna, så att poolen förblir fräsch och inga övergivna uttag stör; det är keepalive_requests och keepalive_timeout. Efter N förfrågningar stänger NGINX av anslutningen medvetet och återupprättar den vid behov, vilket dämpar effekterna av nätverksfördröjningar. Jag ställer in idle-timeouten ganska kort, oftast mellan 30 och 120 sekunder, så att backend-servrarna inte bryter anslutningen i förtid. Det är viktigt att ställa in värdena rätt: NGINX-värdet får aldrig överstiga app-serverns timeout, annars blir det många återuppkopplingar. Den som vill fördjupa sig i bakgrunden hittar praktiska tips i artikeln Keepalive-timeout, som förklarar typiska värden och växelverkan.
För att underlätta orienteringen visar jag vanliga startvärden och deras respektive syfte i en överskådlig Tabell. Riktvärdena fungerar som utgångspunkt och hamnar ofta något högre eller lägre efter övervakning. En för kort tidsperiod leder till onödiga återuppbyggnader, medan en för lång tidsperiod håller kvar gamla anslutningar. Antalet förfrågningar per anslutning skyddar mot extremvärden utan att tömma poolen. Med dessa nyckeltal kan jag mycket snabbt få fram fungerande Standardinställningar.
| Parametrar | Syfte | riktvärde | Tips om tuning |
|---|---|---|---|
| keepalive | Storleken på idle-poolen per arbetare | 32-64 | Anpassa efter den samtidiga belastningen per arbetare |
| keepalive_requests | Max. antal förfrågningar per anslutning | 500–1000 | Vid långa sändningar bör man sätta gränsen något högre |
| keepalive_timeout | Maximal inaktivitetstid per anslutning | 60-talet | Kortare eller samma tidsgräns för inaktivitet i backend |
Bestämma poolstorlek utifrån antalet samtidiga anslutningar
Jag väljer poolstorleken inte utifrån antalet förfrågningar per sekund, utan utifrån Samtidighet per arbetare. Först beräknar jag det genomsnittliga och det maximala antalet parallella backend-förfrågningar. Därefter delar jag dessa siffror med antalet NGINX-arbetare och avrundar uppåt. För 200 samtidiga förfrågningar med fyra arbetare blir det cirka 50 per arbetare, vilket innebär att keepalive 64 passar som startvärde. På så sätt håller jag socklarna tillgängliga utan att ha onödigt många öppna Anslutningar för att binda.
Att medvetet utnyttja särdragen i nyare versioner av NGINX
I de senaste versionerna är återanvändning ofta tillåten som standard, men gränserna är ganska konservativa; jag anger ändå värdena explicit . Detta säkerställer reproducerbarhet, underlättar finjusteringen och förhindrar överraskningar efter en uppdatering. Med parametern „local“ kan jag valfritt begränsa återanvändningen till en viss plats om säkerhetsprofiler eller header-policyer skiljer sig åt. På så sätt förblir åtskillnaden tydlig utan att man globalt går miste om fördelarna med återanvändning. Med tydliga värden dokumenterar jag avsikter och sparar tid senare Analystid.
Övervakning och mätvärden: Fungerar konfigurationen verkligen?
Jag kontrollerar först antalet nya backend-anslutningar per sekund; en tydlig minskning visar att åtgärderna har gett resultat Återanvändning. Sedan tittar jag på upstream_connect_time, som ligger nära noll vid träffar i poolen. Fel i loggarna, särskilt återanslutningar, tyder på tidsgränser som ligger bakom backend-värdena. Dessutom korrelerar jag backend-CPU och latenser med andelen återanvända anslutningar. För en djupare förståelse av Återanvändning av anslutningar Exempel som visar effekterna vid olika belastningsmönster är till hjälp.
Snabbt åtgärda vanliga felkällor
Om HTTP/1.1 saknas till backend blir anslutningarna kortlivade, oavsett hur högt jag keepalive ställer in. Om klienten skickar „Connection: close“ och jag vidarebefordrar rubriken ofiltrerad, stänger backenden varje anslutning direkt efter svaret. Om tidsgränserna för inaktivitet inte stämmer överens avslutar appen anslutningen först och NGINX får en återställning vid nästa begäran. En överdimensionerad pool håller för många socklar öppna och slösar bort minne och portar. Jag kontrollerar dessa fyra punkter vid varje analys som Först, eftersom de förklarar 90 % av alla problem.
Praktiskt exempel: Referenskonfiguration för hög genomströmning
Med några få anvisningar får jag en kraftigt belastad proxy att fungera snabbt och pålitligt och säkerställer en korrekt vidarebefordran av rubriker; följande modell har visat sig fungera väl och är lätt att anpassa. Jag ställer in keepalive på 64, begränsar antalet förfrågningar per anslutning till 1 000 och har en inaktivitetstid på 60 sekunder. Dessutom vidarebefordrar jag värd- och vidarebefordringsinformation korrekt så att backend-systemen kan tillämpa logik och hastighetsbegränsning. Denna kombination skonar CPU:n, förkortar svarstiderna och hanterar belastningstoppar på ett mer smidigt sätt. Det är precis så jag uppnår en väl beräknbar Prestanda.
upstream app_backend {
server 10.0.1.10:3000 max_fails=2 fail_timeout=30s;
server 10.0.1.11:3000 max_fails=2 fail_timeout=30s;
keepalive 64;
keepalive_requests 1000;
keepalive_timeout 60s;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Webbhotellsmiljöer och driftsaspekter som verkligen spelar roll
Jag placerar ofta NGINX framför PHP-FPM-, Node.js- eller Java-tjänster och ser till att nätverksfördröjningarna hålls låga och att tidsgränserna i backend är konsekventa; detta ger Planerbarhet. En stabil nätverkskonfiguration i kärnan med lämpliga socket-gränser förhindrar att ett stort antal öppna anslutningar kolliderar. En jämn CPU-fördelning och snabba lagringsvägar hjälper backend-servrarna att upprätthålla korta svarstider. Dessutom ser jag till att konfigurationerna versioneras så att ändringar förblir spårbara. Med denna disciplin klarar systemet även trafiktoppar reagerbar.
Bästa praxis för löpande verksamhet
Jag börjar med keepalive 32–64, 500–1000 förfrågningar per anslutning och 60 sekunders inaktivitetstid, mäter sedan systematiskt och justerar värdena; det ger snabba framgångar. Varje ändring följer jag upp med mätvärden för anslutningshastighet, latens och felmönster tills kurvorna blir mer stabila. Storleken på poolen anpassar jag efter antalet samtidiga förfrågningar, inte efter den råa genomströmningen per sekund. Timeouts får aldrig vara längre än motsvarigheterna i backend-stacken, annars riskerar man sporadiska återställningar. Den som vill justera hastigheten mer ingående hittar tips om finjustering under Optimera keepalive-förfrågningar, vilket gör återvinningen lätt att hantera.
Justering av proxy-timeouts och TCP-keepalive
Förutom de rena Keepalive-parametrarna finjusterar jag transporttidsgränserna noggrant. Kombinationen av proxy_anslutning_timeout, proxy_send_timeout och proxy_read_timeout bestämmer hur tålmodig NGINX är vid uppbyggnad, sändning och mottagning. Jag ställer aldrig in dessa värden högre än motsvarande värden i backend, utan något lägre, så att fel upptäcks tidigt och inte eskalerar på app-sidan. Dessutom aktiverar jag proxy_socket_keepalive, så att operativsystemet med jämna mellanrum skickar livstecken via inaktiva socklar och upptäcker halvöppna anslutningar. Detta förhindrar att döda anslutningar blir kvar i poolen och orsakar latensspikar vid nästa begäran.
server {
listen 80;
location / {
proxy_pass http://backend_pool;
proxy_connect_timeout 3s; # avbryt snabbt om anslutning inte är möjlig
proxy_send_timeout 30s; # Skrivning till backend
proxy_read_timeout 30s; # Svar från backend
proxy_socket_keepalive on; # Aktivera OS-TCP-keepalive
}
}
För strömmar som pågår under lång tid (t.ex. SSE eller WebSockets) ökar jag endast tidsgränsen för läsning, medan anslutningen förblir aktiv. På så sätt kan jag reagera snabbt på felaktiga mål, samtidigt som legitima, långa svar får passera ostört.
Resursplanering: worker_connections, FD:er och tillfälliga portar
En ren keepalive-pool hjälper inte om gränserna för filbeskrivare eller portintervall är uttömda. Jag planerar därför att arbetare_anslutningar och arbetare_rlimit_nofile med en viss marginal. Grovt räknat: Öppna FD:er ≈ (samtidiga klientanslutningar + samtidiga backend-anslutningar + poolade inaktiva socklar) per arbetare. Om jag använder flera uppströms med pooler multipliceras behovet. Jag är också uppmärksam på systemets område för tillfälliga portar, eftersom NGINX agerar som en TCP-klient mot backend och ackumulerar TIME_WAIT-tillstånd.
worker_processes auto;
worker_rlimit_nofile 131072;
events {
worker_connections 8192;
}
# Linux-exempel (sysctl):
net.core.somaxconn = 4096
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 15
Jag väljer en konservativ strategi: jag avbryter inte TIME_WAIT på ett aggressivt sätt, utan sänker istället anslutningsfrekvensen med hjälp av keepalive. På så sätt förblir kärnparametrarna icke-kritiska och beteendet förutsägbart.
Upstream-zoner, balanseringsstrategi och DNS-rotation
Om det finns flera arbetare delar jag balanseringsstatus via en zon, så att avbrott och belastning förblir konsekventa. Keepalive-socklarna finns visserligen fortfarande per worker, men fördelningen blir jämnare. För dynamiska backend-tjänster som flyttas via DNS ställer jag in „resolve“ i serverraderna och definiera en resolver. Viktigt: När IP-adresserna roterar återanvänder inte poolen omedelbart alla gamla socklar; därför anser jag att keepalive_requests och tidsgränser inom rimliga ramar, så att förnyelsen snabbt får genomslag.
upstream backend_pool {
zone backend_zone 128k; # delar balancerarens tillstånd
least_conn; # rättvis fördelning vid långa förfrågningar
server app-1.internal:8080 resolve;
server app-2.internal:8080 resolve;
keepalive 64;
keepalive_requests 1000;
keepalive_timeout 60s;
}
resolver 10.0.0.2 valid=30s;
resolver_timeout 5s;
proxy_next_upstream error timeout http_502 http_504;
proxy_next_upstream_tries 2; # få, riktade försök
För sessioner som är knutna till en specifik backend-nod (t.ex. sticky-state) kombinerar jag återanvändning med ip_hash eller en extern sessionsmekanism. Detta förhindrar att anslutningspoolning stör sessionskonsistensen.
TLS till backend: SNI, återanvändning av sessioner och krypteringsalgoritmer
Ju mer TLS används i backend-vägen, desto viktigare är Keepalive. Jag aktiverar SNI, anger det förväntade namnet och ser till att TLS-sessionen återanvänds. Detta minskar handskakningskostnaderna och jämnar ut latensspikar. Jag väljer krypteringssviter och protokoll med försiktighet, utan att stänga ute äldre backend-system. Vid certifikatverifiering (valfritt) måste förtroendekedjan vara komplett, annars bryts anslutningarna sporadiskt.
upstream https_backend {
server backend.example.local:443;
keepalive 32;
}
server {
listen 443 ssl;
location / {
proxy_pass https://https_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_ssl_server_name on;
proxy_ssl_name backend.example.local;
proxy_ssl_session_reuse on;
proxy_ssl_protocols TLSv1.2 TLSv1.3;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
# optional: proxy_ssl_verify on;
# optional: proxy_ssl_trusted_certificate /etc/nginx/ca.pem;
}
}
När jag själv övervakar backend-sidan aktiverar jag sessionstickets eller -cacher där och kontrollerar med hjälp av mätvärden om återupptagningsgraden ökar. I kombination med Keepalive uppnår jag på så sätt genomgående korta anslutnings- och handskakningstider.
Särskilda fall: gRPC, WebSockets och anslutningsbunden autentisering
Med gRPC fungerar NGINX uppströms via HTTP/2. Här ger ofta ett fåtal långvariga anslutningar med många strömmar de bästa resultaten; poolen förblir liten men stabil. För WebSockets Jag ställer in långa läs-timeouts och behåller header-logiken från map-lösningen, så att uppgraderingsanslutningar inte stängs av misstag. NTLM eller andra anslutningsbundna autentiseringsmetoder kräver anslutningsbindning; jag delar upp sådana vägar i separata platser och minskar där poolning eller återanvändning, så att säkerhetshandskakningar inte blandas ihop mellan klienter.
# gRPC-exempel
location /grpc.Service/ {
grpc_pass grpc://backend_pool;
grpc_read_timeout 300s; Tillåt #-långa strömmar
}
Det är avgörande att fastställa en konsekvent anslutningspolicy för varje väg och endast använda Keepalive i stor utsträckning där det inte är semantiskt kritiskt.
Mätbarhet i praktiken: åtkomstloggar med uppströms-tidsangivelser
Jag utökar Access-loggen med uppströmsmått. På så sätt kan jag med ett ögonkast se om ett svar kom från en socket i poolen (mycket kort anslutningstid) och hur ofta backend-fel uppstår. Dessutom loggar jag anslutningsnumret och antalet förfrågningar via den aktuella klientanslutningen för att kunna hitta korrelationer.
log_format upstream_timing '$remote_addr - $host "$request" '
'up=$upstream_addr '
'sc=$status usc=$upstream_status '
'cc=$connection cr=$connection_requests '
'tc=$upstream_connect_time '
'th=$upstream_header_time '
'tr=$upstream_response_time';
access_log /var/log/nginx/access_upstream.log upstream_timing;
Dessutom använder jag operativsystemets statusändpunkter och socketstatistik. Ett normalt tillstånd kännetecknas av: sjunkande anslutningshastighet till backenden, kortare upstream_connect_time, stabila svarstider och nästan inga anslutningsåterställningar. Avvikelser tyder nästan alltid på felaktigt inställda tidsgränser eller för små/för stora pooler.
Lanseringsstrategi och riskminimerande finjustering
Jag arbetar stegvis: små steg, mäta, justera. Först aktiverar jag Keepalive i måttlig utsträckning, därefter justerar jag timeouts och antalet förfrågningar per anslutning. Jag tillämpar ändringarna genom att ladda om sidan, utan att bryta aktiva anslutningar. På så sätt förblir risken låg och effekterna går att tydligt koppla till varandra.
# Validera ändringar och ladda om utan driftstopp
nginx -t && nginx -s reload
När jag hanterar flera uppströmsprocesser finjusterar jag dem en efter en, med början på den mest kritiska vägen. Varje steg får ett observationsfönster så att mönster i mätvärdena tydligt framträder. Först därefter skalar jag upp eller ner värdena.
En kort sammanfattning för din omvända proxy
Jag använder HTTP/1.1, tömmer Connection-rubriken och väljer poolstorleken utifrån antalet samtidiga förfrågningar, inte utifrån RPS; detta bidrar till att Effekt. Med keepalive_requests och keepalive_timeout håller jag anslutningarna aktiva och undviker överraskningar på grund av föråldrade socklar. Övervakningen visar om upstream_connect_time tenderar att närma sig noll och om anslutningsfrekvensen till backenden minskar. Vid fel kontrollerar jag först protokollversion, vidarebefordran av rubriker, tidsgränser och poolstorlek. Så här håller du din NGINX-proxy igång under hög belastning lyhörd och förutsägbar.


