Ik configureer NGINX Upstream Keepalive zodanig dat de reverse proxy minder verbindingen tot stand brengt, lagere latenties biedt en pieken in de belasting betrouwbaar opvangt. Daarbij pas ik Grootte van het zwembad, tijdslimieten en headers doelgericht aan, zodat verbindingen opnieuw worden gebruikt en het gegevenspad compact blijft.
Centrale punten
- HTTP/1.1 afdwingen en Connection-headers opschonen
- keepalive per werknemer de juiste afmetingen bepalen
- Time-outs aanpassen aan backend-waarden
- Verzoeken/Verbinding beperken en recyclen
- Controle voor verbindingssnelheid en latentie
Waarom Upstream Keepalive de inspanning voor het tot stand brengen van verbindingen drastisch vermindert
Zonder hergebruik opent NGINX per verzoek een nieuwe backend-verbinding, wat extra handshakes, meer CPU-cycli en extra kernelbronnen kost; precies hier komt Keepalive . Ik laat NGINX reeds opgebouwde, op dat moment inactieve sockets in de cache opslaan en gebruiken voor volgende verzoeken, waardoor de verbindingstijden meetbaar afnemen. Dit verlaagt het aantal verbindingen per seconde, vermindert pieken in de backlog en remt contextwisselingen in het besturingssysteem af. Vooral bij TLS-verbindingen met de backend bespaar ik merkbaar tijd door hergebruikte sessies. Zo blijft de responsketen ook bij een hoge doorvoersnelheid betrouwbare en reageert soepel.
Het basisprincipe en de keepalive-richtlijn in de upstream
De richtlijn keepalive In het upstream-blok wordt het aantal tijdelijk opgeslagen, inactieve backend-verbindingen per worker beperkt. Deze limiet geldt niet globaal, maar strikt per worker-proces, en daarom houd ik het aantal workers altijd goed in de gaten. Als de pool vol is, sluit NGINX eerst de verbinding die het langst niet is gebruikt, zodat er ruimte is voor nieuwe sockets. Voor hergebruik heeft de proxy-zijde HTTP/1.1 en een geneutraliseerde Connection-header nodig. Zonder deze voorwaarden blijft de pool leeg, hoewel ik in de upstream „keepalive“ instel, wat veel beheerders in het begin verrast.
upstream backend_pool {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
keepalive 32; # inactieve verbindingen per worker
keepalive_requests 1000; # hergebruik na N verzoeken
keepalive_timeout 60s; # levensduur inactieve verbindingen
}
server {
listen 80;
location / {
proxy_pass http://backend_pool;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Verplichte richtlijnen in het Location-blok: HTTP/1.1 en header-controle
Ik dwing NGINX in het proxypad om HTTP/1.1 te gebruiken, omdat Keepalive met HTTP/1.0 niet goed werkt en verbindingen onnodig worden verbroken; de richtlijn proxy_http_versie 1.1 is daarom verplicht. Daarnaast verwijder ik de Connection-header voor reguliere verzoeken, zodat de backend geen „close“-instructie ontvangt. Voor upgrades zoals WebSockets stel ik via map gericht „Connection: Upgrade“ in, zonder het normale hergebruik te beïnvloeden. Zo blijft het verbindingsbeleid consistent en losgekoppeld van client-headers. Juist deze kleine wijziging voorkomt veel moeilijk te achterhalen Foutbeelden.
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;
"" "";
}
Fijnafstemming: de juiste instellingen kiezen voor keepalive_requests en keepalive_timeout
Met twee stelschroeven regel ik de levensduur en vernieuwing van de verbindingen, zodat het forum fris blijft en er geen verlaten topics storend zijn; dat zijn keepalive_requests en keepalive_timeout. Na N verzoeken sluit NGINX de verbinding doelbewust af en brengt deze indien nodig opnieuw tot stand, wat de gevolgen van veroudering in het netwerk opvangt. De idle-timeout stel ik vrij kort in, meestal tussen 30 en 120 seconden, zodat backends de verbinding niet eerder verbreken. Afstemming is belangrijk: de NGINX-waarde ligt nooit hoger dan de time-out van de app-servers, anders stapelen de verbindingsresets zich op. Wie zich verder in de achtergronden wil verdiepen, vindt praktische tips in het artikel Keepalive-time-out, waarin de typische waarden en interacties worden toegelicht.
Om snel een overzicht te krijgen, zet ik de gangbare startwaarden en het bijbehorende doel in een overzichtelijke tabel Tabel. De richtwaarden dienen als uitgangspunt en vallen na monitoring vaak iets hoger of lager uit. Een te korte tijdsduur leidt tot onnodige heropbouw, een te lange houdt oude verbindingen in stand. Het aantal verzoeken per verbinding beschermt ik tegen uitschieters, zonder de pool leeg te maken. Met deze kerngegevens stel ik zeer snel werkende Standaard.
| Parameters | Doel | richtwaarde | Opmerking over tuning |
|---|---|---|---|
| keepalive | Grootte van de idle-pool per worker | 32-64 | Afstemmen op gelijktijdige belasting per worker |
| keepalive_requests | Max. aantal verzoeken per verbinding | 500–1000 | Bij lange streams iets hoger instellen |
| keepalive_timeout | Max. inactieve tijd per verbinding | jaren ’60 | Kortere of dezelfde time-out voor backend-inactiviteit |
De grootte van de pool bepalen op basis van het aantal gelijktijdige verbindingen
Ik kies de poolgrootte niet op basis van het aantal verzoeken per seconde, maar op basis van Concurrentie per worker. Eerst bepaal ik het gemiddelde en het maximale aantal gelijktijdige backend-verzoeken. Vervolgens deel ik deze getallen door het aantal NGINX-workers en rond ik het resultaat naar boven af. Bij 200 gelijktijdige verzoeken en vier workers kom ik uit op ongeveer 50 per worker, waardoor keepalive 64 een geschikte startwaarde is. Zo houd ik sockets beschikbaar zonder onnodig veel open Verbindingen te binden.
Bewust gebruikmaken van de bijzondere kenmerken van recentere NGINX-versies
In de huidige versies is hergebruik vaak standaard toegestaan, maar gelden er vrij conservatieve limieten; ik voer de waarden toch in expliciet . Dit zorgt voor reproduceerbaarheid, vergemakkelijkt het afstemmen en voorkomt verrassingen na een update. Via de parameter „local“ beperk ik het hergebruik optioneel tot één locatie, wanneer beveiligingsprofielen of header-beleidsregels verschillen. Zo blijft de scheiding duidelijk, zonder dat de voordelen van hergebruik op globaal niveau verloren gaan. Met duidelijke waarden leg ik mijn bedoelingen vast en bespaar ik later Analysetijd.
Monitoring en statistieken: werkt de configuratie echt?
Ik controleer eerst het aantal nieuwe backend-verbindingen per seconde; een duidelijke daling wijst erop dat de maatregelen effect sorteren Hergebruik. Vervolgens bekijk ik de `upstream_connect_time`, die bij treffers in de pool bijna nul is. Fouten in de logbestanden, met name het opnieuw opstarten van verbindingen, wijzen op tijdslimieten die ten grondslag liggen aan de backend-waarden. Daarnaast breng ik de backend-CPU en latenties in verband met het percentage hergebruikte verbindingen. Voor een dieper inzicht in de Hergebruik van verbindingen Voorbeelden die de effecten bij verschillende belastingspatronen laten zien, helpen daarbij.
Typische foutbronnen snel verhelpen
Als HTTP/1.1 naar de backend ontbreekt, blijven verbindingen van korte duur, hoe hoog ik ook keepalive stel in. Als de client „Connection: close“ verstuurt en ik de header ongefilterd doorgeef, sluit de backend elke verbinding direct na het antwoord af. Als de idle-time-outs niet overeenkomen, verbreekt de app-zijde de verbinding als eerste en krijgt NGINX bij het volgende verzoek een reset. Een te grote pool houdt te veel sockets open en verspilt werkgeheugen en poorten. Ik controleer deze vier punten bij elke analyse als Ten eerste, omdat ze 90 % van alle problemen verklaren.
Praktijkvoorbeeld: referentieconfiguratie voor een hoge doorvoer
Met slechts enkele instructies zorg ik ervoor dat een zwaar belaste proxy weer snel en betrouwbaar werkt en zorg ik voor een correcte doorsturing van headers; het volgende patroon heeft zijn waarde bewezen en is eenvoudig toe te passen aanpassen. Ik stel keepalive in op 64, beperk het aantal verzoeken per verbinding tot 1000 en hanteer een inactieve tijd van 60 seconden. Daarnaast geef ik host- en doorstuurgegevens correct door, zodat backends logica en tariefbeperking kunnen toepassen. Deze combinatie ontlast de CPU, verkort de responstijden en vangt pieken in de belasting beter op. Precies zo bereik ik een goed voorspelbare Prestaties.
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;
}
}
Hostingomgevingen en operationele aspecten die er echt toe doen
Ik plaats NGINX vaak vóór PHP-FPM-, Node.js- of Java-services en zorg ervoor dat de netwerklatentie laag blijft en dat de time-outs van de backend consistent zijn; dat levert Planbaarheid. Een solide netwerkconfiguratie op kernelniveau met passende socketlimieten voorkomt dat te veel open verbindingen met elkaar in conflict komen. Een gelijkmatige CPU-toewijzing en snelle opslagpaden helpen de backends om korte responstijden te behouden. Daarnaast zorg ik voor configuraties met versienummers, zodat wijzigingen traceerbaar blijven. Met deze discipline blijft het systeem stabiel tijdens pieken in het verkeer reageerbaar.
Best practices voor lopende activiteiten
Ik begin met een keepalive van 32–64, 500–1000 verzoeken per verbinding en een inactieve tijd van 60 seconden, meet vervolgens systematisch en pas de waarden aan; dat levert snelle successen. Bij elke wijziging houd ik statistieken bij over de verbindingssnelheid, latentie en foutpatronen, totdat de grafieken stabieler worden. De grootte van de pool stem ik af op het aantal gelijktijdige verzoeken, niet op de bruto-doorvoer per seconde. Time-outs mogen nooit langer duren dan hun tegenhangers in de backend-stack, anders bestaat het risico op sporadische resets. Wie de instellingen nog verder wil verfijnen, vindt aanwijzingen voor fijnafstemming onder Keepalive-verzoeken optimaliseren, waardoor recycling goed beheersbaar is.
Afstemming van de proxy-time-outs en TCP-keepalive
Naast de pure keepalive-parameters stel ik de transporttijdlimieten nauwkeurig af. De drie-eenheid van proxy_connect_timeout, proxy_send_timeout en proxy_read_timeout bepaalt hoe geduldig NGINX is bij het opbouwen, verzenden en ontvangen. Ik stel deze waarden nooit hoger in dan de overeenkomstige waarden in de backend, maar net iets lager, zodat fouten vroeg zichtbaar worden en niet escaleren aan de app-zijde. Daarnaast schakel ik proxy_socket_keepalive, zodat het besturingssysteem met regelmatige tussenpozen een signaal verstuurt via inactieve sockets en halfopen verbindingen detecteert. Dit voorkomt dat dode verbindingen in de pool achterblijven en bij het volgende verzoek voor pieken in de latentie zorgen.
server {
listen 80;
location / {
proxy_pass http://backend_pool;
proxy_connect_timeout 3s; # snel afbreken als er geen verbinding tot stand kan worden gebracht
proxy_send_timeout 30s; # Schrijven naar de backend
proxy_read_timeout 30s; # Antwoorden van de backend
proxy_socket_keepalive on; # OS-TCP-keepalive activeren
}
}
Voor langlopende streams (bijvoorbeeld SSE of WebSockets) verhoog ik uitsluitend de read-time-out, terwijl de verbinding intact blijft. Zo reageer ik snel op defecte bestemmingen, maar laat ik legitieme, lange antwoorden ongestoord doorlopen.
Resourceplanning: worker_connections, FD's en tijdelijke poorten
Een schone keepalive-pool heeft geen zin als de limieten voor bestandsdescriptoren of poortbereiken worden bereikt. Daarom ben ik van plan om werker_verbindingen en worker_rlimit_nofile met een marge. Ik maak een ruwe schatting: open FD’s ≈ (gelijktijdige clientverbindingen + gelijktijdige backendverbindingen + gepoolde idle-sockets) per worker. Als ik meerdere upstreams met pools gebruik, neemt de behoefte toe. Ook let ik op het bereik van de tijdelijke poorten van het systeem, aangezien NGINX zich richting de backend gedraagt als een TCP-client en TIME_WAIT-toestanden verzamelt.
worker_processes auto;
worker_rlimit_nofile 131072;
events {
worker_connections 8192;
}
# Linux-voorbeelden (sysctl):
net.core.somaxconn = 4096
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 15
Ik pak het voorzichtig aan: TIME_WAIT niet agressief wegwerken, maar de verbindingsfrequentie via Keepalive verlagen. Zo blijven de kernelparameters niet-kritisch en blijft het gedrag voorspelbaar.
Upstream-zones, balancer-strategie en DNS-rotatie
Als er meerdere workers zijn, deel ik de status van de balancer via een zone, zodat uitval en belasting consistent blijven. Keepalive-sockets blijven weliswaar per worker bestaan, maar de verdeling wordt gelijkmatiger. Bij dynamische backends die via DNS verhuizen, stel ik „resolve“ in de serverregels en definieer een resolver. Belangrijk: wanneer IP-adressen rouleren, hergebruikt de pool niet onmiddellijk alle oude sockets; ik ben daarom van mening dat keepalive_requests en tijdslimieten die binnen een realistisch kader vallen, zodat de vernieuwing snel effect sorteert.
upstream backend_pool {
zone backend_zone 128k; # verdeelt de status van de balancer
least_conn; # eerlijke verdeling bij lange verzoeken
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; # enkele, gerichte herhalingen
Voor sessies die aan een bepaald backend-knooppunt zijn gekoppeld (bijvoorbeeld sticky-state), combineer ik hergebruik met ip_hash of een extern sessiemechanisme. Dit voorkomt dat connection pooling de sessiecohesie verstoort.
TLS naar de backend: SNI, hergebruik van sessies en versleutelingsalgoritmen
Hoe intensiever TLS in het backend-pad wordt gebruikt, hoe waardevoller Keepalive is. Ik activeer SNI, stel de verwachte naam in en zorg ervoor dat de TLS-sessie wordt hergebruikt. Dit verlaagt de handshake-kosten en vlakkt pieken in de latentie af. Ik kies cipher-suites en protocollen op een restrictieve manier, zonder oudere backends uit te sluiten. Bij certificaatcontrole (optioneel) moet de vertrouwensketen volledig zijn, anders vallen verbindingen sporadisch weg.
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;
# optioneel: proxy_ssl_verify aan;
# optioneel: proxy_ssl_trusted_certificate /etc/nginx/ca.pem;
}
}
Als ik zelf de backend-kant beheer, schakel ik daar sessietickets of -caches in en controleer ik aan de hand van statistieken of de herstelpercentages stijgen. In combinatie met Keepalive bereik ik zo blijvend lage verbindings- en handshake-tijden.
Speciale gevallen: gRPC, WebSockets en verbindingsgebonden authenticatie
Op gRPC werkt NGINX upstream via HTTP/2. Hier leveren enkele langdurige verbindingen met veel streams vaak de beste resultaten op; de pool blijft klein, maar stabiel. Voor WebSockets Ik stel lange read-time-outs in en behoud de header-logica uit de map-oplossing, zodat upgrade-verbindingen niet per ongeluk worden verbroken. NTLM of andere verbindingsgebonden authenticatiemethoden vereisen ‘connection pinning’; ik splits dergelijke paden op in aparte locaties en beperk daar het poolen of hergebruik, zodat beveiligingshandshakes niet tussen clients door elkaar raken.
# gRPC-voorbeeld
location /grpc.Service/ {
grpc_pass grpc://backend_pool;
grpc_read_timeout 300s; # lange streams toestaan
}
Het is van cruciaal belang om per pad een consistent verbindingsbeleid vast te stellen en keepalive alleen op grote schaal toe te passen waar dit semantisch niet van cruciaal belang is.
Meetbaarheid in de praktijk: toegangslogs met upstream-timings
Ik breid het Access-log uit met upstream-statistieken. Zo zie ik in één oogopslag of een antwoord afkomstig was van een socket uit de pool (zeer korte connectietijd) en hoe vaak er backend-fouten optreden. Daarnaast registreer ik het verbindingsnummer en het aantal verzoeken via de huidige clientverbinding om correlaties te vinden.
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;
Daarnaast maak ik gebruik van status-eindpunten en socketstatistieken van het besturingssysteem. Een gezonde status laat het volgende zien: een dalende verbindingssnelheid naar de backend, een kortere upstream_connect_time, stabiele responstijden en nauwelijks verbindingresets. Afwijkingen duiden bijna altijd op niet-afgestemde tijdslimieten of te kleine/te grote pools.
Uitrolstrategie en risicovrije afstemming
Ik ga stapsgewijs te werk: kleine stapjes, meten, aanpassen. Eerst activeer ik Keepalive in gematigde mate, daarna pas ik de time-outs en het aantal verzoeken per verbinding aan. Wijzigingen pas ik toe door de pagina opnieuw te laden, zonder actieve verbindingen te verbreken. Zo blijft het risico beperkt en zijn de effecten duidelijk te herleiden.
# Wijzigingen valideren en laden zonder downtime
nginx -t && nginx -s reload
Als ik meerdere upstreams beheer, stem ik ze een voor een af, te beginnen met het meest kritieke pad. Elke fase krijgt een observatieperiode, zodat patronen in de statistieken duidelijk naar voren komen. Pas daarna pas ik de waarden naar boven of naar beneden aan.
Beknopte samenvatting voor je reverse proxy
Ik gebruik HTTP/1.1, laat de Connection-header leeg en bepaal de poolgrootte op basis van het aantal gelijktijdige verzoeken, niet op basis van RPS; dat draagt bij aan de Prestaties. Met `keepalive_requests` en `keepalive_timeout` houd ik verbindingen actief en voorkom ik verrassingen door verouderde sockets. Monitoring laat zien of `upstream_connect_time` naar nul neigt en of de verbindingssnelheid naar de backend afneemt. Bij fouten controleer ik eerst de protocolversie, het doorgeven van headers, time-outs en de poolgrootte. Zo blijft je NGINX-proxy stabiel onder hoge belasting responsief en voorspelbaar.


