...

NGINX Keepalive-verzoeken optimaliseren: optimale webserverprestaties door gerichte afstemming

Met nginx keepalive Ik verlaag de kosten voor het opbouwen van verbindingen, verminder het aantal handshakes en versnel de responstijden merkbaar. Doelgericht afgestemde time-outs, verzoeklimieten per verbinding en hergebruikte upstream-sockets leveren meetbare prestatiewinst op zonder nieuwe hardware.

Centrale punten

  • Time-outs Verstandig kiezen: de inactieve tijd zo kort als nodig, zo lang als nuttig.
  • Verzoeken Beperken per verbinding: duurzame sockets, geen vastlopers.
  • Upstream-pools Activeren: permanente backend-verbindingen per worker.
  • Werknemer en verbindingen afstemmen: voldoende slots voor inactieve en actieve clients.
  • Controle instellen: connectiepercentage, latentie en fouten in de gaten houden.

NGINX Keepalive: effecten en kosten

Ik houd TCP-verbindingen bewust open, omdat Handdrukken duur zijn en bij veel kleine verzoeken de overhand hebben. Persistente sockets besparen niet alleen RTT’s, ze zorgen ook voor een gelijkmatiger CPU-gebruik, omdat de cryptografie voor TLS minder vaak wordt gestart. Elke open verbinding neemt echter Bronnen, zoals bestandsdescriptoren en buffers, die ik in de gaten moet houden. De kunst zit hem in de juiste balans: voldoende hergebruik voor snelheid, voldoende capaciteit voor nieuwe verbindingen bij pieken in het verkeer. Wie die balans weet te vinden, bereikt constant lage TTFB-waarden en een snelle gebruikerservaring.

HTTP/2 en HTTP/3: multiplexing en keepalive

Met HTTP/2 en HTTP/3 daalt het aantal benodigde verbindingen per client, omdat er meerdere streams via één verbinding lopen. Keepalive blijft echter van belang: die ene verbinding moet betrouwbaar open blijven, anders gaat het voordeel van multiplexing verloren door het veelvuldig opnieuw tot stand brengen van verbindingen.

Ik let op de specifieke idle-parameters voor moderne protocollen en zorg ervoor dat de waarden aansluiten bij de time-outs van mijn client. Voor tests begin ik met gematigde waarden en verhoog ik deze bij een stabiele belasting, totdat het aantal herverbindingen afneemt en de latentie constant blijft.

http {
    # HTTP/2: time-out voor inactieve, maar geopende streams
    http2_idle_timeout 60s;

    # HTTP/3/QUIC: vergelijkbare logica voor op UDP gebaseerde verbindingen
    http3_idle_timeout 60s;

    # TLS-hervatting vermindert de kosten van de handshake bij nieuwe verbindingen
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
}

Multiplexing vermindert het aantal benodigde parallelle TCP/QUIC-verbindingen, maar niet het belang van de juiste time-outs. Wie HTTP/2/3 gebruikt, kan de time-outs aan de clientzijde vaak wat ruimer instellen, omdat veel kleine bronnen via hetzelfde kanaal worden verzonden. Belangrijk: meetbaar blijven Tijd tot eerste byte, foutpercentages en actieve streams per verbinding.

Client-Keepalive correct instellen

Voor browserclients regel ik hergebruik via keepalive_timeout en keepalive_requests, zodat sockets lang genoeg actief blijven zonder eindeloos te blokkeren. Als uitgangspunt hanteer ik een time-out van 30–60 seconden en 100–300 verzoeken per verbinding; daarna pas ik de instellingen aan op basis van de statistieken. Een gedetailleerd overzicht vind je hier Handleiding voor keepalive-time-out, waarin de gevolgen voor de latentie en de serverbronnen worden uitgelegd. Kortere time-outs zijn geschikt bij zeer veel korte verzoeken, terwijl langere tijdsvensters helpen bij periodieke API-toegangen. Om te beginnen stel ik duidelijke standaardinstellingen in en meet ik het effect op open verbindingen en foutmeldingen.

http {
    # Inactieve verbindingen met de client
    keepalive_timeout 60s;
    # Maximum aantal verzoeken per TCP-verbinding
    keepalive_requests 200;

    # Optioneel: Keep-Alive uitschakelen voor bepaalde clients (legacy-bugs)
    # keepalive_disable msie6;
}

Upstream-keepalive in de reverse proxy

Tussen NGINX en de backend-apps maak ik gebruik van persistente upstream-sockets, omdat de verbinding met PHP-FPM, Node.js of Python-services ook Latency kost. Hiervoor activeer ik in de upstream-pool een passend aantal herbruikbare verbindingen per worker. Belangrijk zijn HTTP/1.1 naar de server toe en een lege Connection-header, anders verbreekt het „close“-verzoek van de client de backend-persistentie. Ik baseer me op het aantal gelijktijdige verzoeken en stel de pool zo in dat er nauwelijks nieuwe verbindingen tot stand komen. Zo daalt de backend-connect-tijd en levert de gehele keten snellere Antwoorden.

upstream backend {
    server 127.0.0.1:9000;
    keepalive 64; # Aantal persistente upstream-verbindingen per worker
}

server {
    location / {
 proxy_pass http://backend;
        proxy_http_version 1.1;
 proxy_set_header Connection "";
 # TCP-keepalive voor upstream-sockets op OS-niveau
 proxy_socket_keepalive on;
    }
}

Dimensionering van het zwembad en het budget voor aansluitingen

Ik bereken pools op realistische wijze: het aantal persistente upstream-verbindingen wordt bepaald door worker_processes × keepalive per upstream. Wie 8 workers en keepalive 64 gebruikt, houdt tot 512 sockets per upstream open – per instantie. Achter een load balancer of bij meerdere upstream-doelen kan dat snel oplopen.

Mijn streefwaarde: voldoende open sockets, zodat het grootste deel van de verzoeken zonder nieuwe Connect wordt bediend, maar er is nog ruimte voor pieken. Ik houd de statistiek „nieuwe upstream-verbindingen per seconde“ in de gaten en verlaag deze totdat verdere vergrotingen van de poolgrootte geen noemenswaardige verbetering van de latentie meer opleveren.

Ik houd ook rekening met Eerlijkheid: Te grote pools kunnen nieuw binnenkomende clients benadelen, omdat worker-slots worden bezet door inactieve verbindingen. Een gematigde limiet in combinatie met actieve monitoring werkt meestal sneller dan het op goed geluk instellen van maximale waarden.

Fijnafstemming: time-outs en verzoeklimieten

Ik combineer de time-out en het verzoeklimiet zodanig dat verbindingen effectief opnieuw worden gebruikt, zonder dat dit leidt tot Langlaufer te worden. Hoge waarden op beide assen minimaliseren het aantal ‘connects’, maar verhogen het risico op vastgelopen sockets bij netwerkproblemen. Lage waarden zorgen voor nieuwe verbindingen, maar kosten extra handshakes. Ik ga stap voor stap te werk, houd fouten in de gaten en pas de instellingen met tussenpozen aan. De volgende tabel toont zinvolle startbereiken voor verschillende gebruikspatronen en biedt een compact Oriëntatie.

Scenario keepalive_timeout keepalive_requests Tip
Veel korte paginabezoeken 10–30 s 100-300 Snelle hergebruikstijd, lage idle-binding
Typische website 60–120 s 200–400 Goede gemiddelde scores voor Assets en HTML
API met periodieke oproepen 60–120 s 300–1000 Hoger hergebruikpercentage voor klanten
Interne diensten / Gateways 30–90 seconden 500–1000+ Constantheid is belangrijker dan een minimaal aantal connects

Worker-tuning en verbindingen

Ik heb werker_processen op 'auto' of op het aantal CPU-kernen en zorg voor voldoende werker_verbindingen omdat inactieve sockets slots bezetten. Te lage limieten verhinderen dat er nieuwe verbindingen tot stand komen, ook al is er nog CPU-capaciteit beschikbaar. Wie met grote keepalive-pools werkt, heeft voldoende descriptoren en event-slots per worker nodig. Een goede inleiding hierover is te vinden in „Worker-Connections opschalen“, waarin de verbanden tussen gebeurtenissen, verbindingen en belasting worden toegelicht. Doordachte instellingen zorgen ervoor dat hergebruik bij inactiviteit en het tot stand brengen van nieuwe verbindingen naast elkaar kunnen plaatsvinden.

worker_processes auto;

events {
    worker_connections 4096;
    # Optioneel: reuseport kan de verdeling op kernelniveau verbeteren
    # multi_accept on;
}

http {
    keepalive_timeout 60s;
    keepalive_requests 200;

 upstream backend {
 server 127.0.0.1:9000;
 keepalive 64;
    }
}

Optimalisatie van het besturingssysteem en de sockets

Ik controleer de systeemlimieten, zodat Keepalive zijn potentieel ten volle kan benutten. Te weinig descriptoren of overvolle socket-wachtrijen leiden tot kunstmatige knelpunten. Naast `ulimit` en `worker_rlimit_nofile` zijn kernelbeperkingen van cruciaal belang.

# Voorbeeldwaarden voor sysctl (met de nodige voorzichtigheid aanpassen en testen)
fs.file-max = 1000000
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 16384
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_syn_backlog = 262144

Ik stem deze waarden af op de omgeving: veel kortstondige verbindingen hebben baat bij een breed poortbereik en korte FIN-/TIME_WAIT-tijden. Bij upstream-keepalive verminder ik Neuconnects, waardoor de TIME_WAIT-drukken afnemen. Daarnaast houd ik rekening met NAT-Apparaten tussen de proxy en de backend: te strenge time-outs bij inactiviteit in het netwerk zorgen ervoor dat verbindingen op onvoorspelbare momenten worden verbroken. Een gematigde limiet voor het aantal verzoeken per socket en TCP-keepalives (proxy_socket_keepalive on;) voorkomen dat verbindingen „verouderd“ raken.

De header en HTTP-versie correct instellen

Ik let op HTTP/1.1 naar de backend, omdat Upstream-Keepalive alleen daarmee werkt. Daarnaast schakel ik actieve verbindingsbeheer via headers uit, zodat NGINX de persistentie zelfstandig beheert. Aan de clientzijde laat ik Keep-Alive volgens de standaard werken en beperk ik de levensduur via time-out en verzoeklimiet. Daarnaast controleer ik de idle-time-outs van de backend en stel ik deze iets hoger in dan bij NGINX om resetfouten te voorkomen. Schone headers zorgen voor de Hergebruik zonder ongewenste sluitingen.

# Voorbeeld: proxy-locatie met correcte headers
location /api/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

Verschil: HTTP Keep-Alive versus TCP Keep-Alive

Ik maak een strikt onderscheid tussen HTTP Keep-Alive (meerdere HTTP-verzoeken per verbinding) en TCP-Keepalive (Tests op besturingssysteemniveau om inactieve verbindingen te detecteren). HTTP Keep-Alive regel ik met keepalive_timeout en keepalive_requests, terwijl TCP-keepalives, afhankelijk van de stack, via proxy_socket_keepalive on; en systeemparameters draaien. Voor backends die via onstabiele netwerken werken, schakel ik TCP-keepalives in om vastgelopen sockets sneller op te ruimen.

Langlopers en speciale gevallen: WebSockets, SSE, gRPC

WebSockets en servergebeurtenissen zijn Langlaufer, die een verbinding gedurende lange tijd openhouden – hier speelt klassieke Reuse een ondergeschikte rol. Ik zorg voor geschikte proxy_read_timeout en bescherm mij met send_timeout tegen Slowloris-effecten. Voor gRPC (op basis van HTTP/2) gelden de overwegingen met betrekking tot multiplexing; ik stel de time-outs voor inactiviteit zo in dat streams niet onnodig worden afgesloten.

location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 300s;
    send_timeout 30s;
}

Bewaking en statistieken

Ik meet het succes aan de hand van kengetallen zoals het percentage nieuwe upstream-verbindingen, stroomopwaartse_verbindingstijd en het aandeel open verbindingen per worker. Dalende connect-rates bij een gelijkblijvend of stijgend aantal verzoeken duiden op succesvol hergebruik. Opvallende time-outs of het opnieuw tot stand brengen van verbindingen wijzen op tegenstrijdige time-outs tussen NGINX en de backend. Daarnaast houd ik het geheugen, de bestandsdescriptoren en de event-queues onder belasting in de gaten. Wie dit regelmatig controleert, ontdekt trends in een vroeg stadium en voorkomt dure Storingen.

Verbeteringen in de logboekregistratie voor meer transparantie bij hergebruik

Om meer inzicht te krijgen, voeg ik verbindingsgegevens toe aan het toegangslogboek. Zo kan ik zien hoe vaak een TCP-verbinding wordt hergebruikt en hoe de verbindingstijden zich ontwikkelen.

log_format keepalive_fmt
  '$remote_addr $host "$request" $status $body_bytes_sent '
  '$request_time $upstream_connect_time '
  'conn:$connection reqs:$connection_requests';

access_log /var/log/nginx/access_keepalive.log keepalive_fmt;

Ik bekijk de mediaan- en P95/P99-waarden van stroomopwaartse_verbindingstijd en de verdeling van $-verbindingsverzoeken. Stijgende Reuse-waarden bij een stabiele latentie betekenen dat de pools en time-outs goed zijn ingesteld.

Typische struikelblokken en oplossingen

Te grote pools vullen de verbindingsslots op, terwijl nieuwe clients moeten wachten; daarom houd ik de grootte gematigd en pas ik deze aan. Verschillende time-outs voor inactiviteit tussen de proxy en de backend leiden tot resets, dus stel ik de backend net iets hoger in dan NGINX. Een vergeten „Connection: close“ in de proxy-header onderbreekt de persistentie, daarom maak ik de header consequent leeg. TLS-onderhandeling kan bij veel nieuwe verbindingen de CPU belasten, wat ik verzacht door een hoger hergebruikspercentage. Bij sporadische netwerkstoringen helpt een gematigde verzoeklimiet per socket, zodat oude Sessies niet eeuwig leven.

Praktijkgerichte configuraties

Voor drukbezochte websites kies ik een korte time-out en een gemiddeld hoge verzoeklimiet, zodat assets efficiënt werken. Bij API’s met terugkerende oproepen verhoog ik de limiet om het aantal TCP- en TLS-handshakes verder te verminderen. Ik dimensioner upstream-pools op basis van de verwachte parallelliteit en test deze met realistisch verkeer. Elke omgeving gedraagt zich anders, daarom controleer ik na wijzigingen de latentie en foutpatronen. Twee voorbeelden illustreren dit Startwaarden, die ik vervolgens met statistieken verfijn.

# Scenario 1: Drukbezochte website
http {
    keepalive_timeout 30s;
    keepalive_requests 300;

 upstream app {
 server 127.0.0.1:8080;
        keepalive 32;
    }

 server {
 listen 443 ssl http2;
 # HTTP/2-idle in de gaten houden
 http2_idle_timeout 45s;
    }
}
# Scenario 2: API met periodieke aanroepen
http {
    keepalive_timeout 75s;
    keepalive_requests 1000;

    upstream api_backend {
 server 127.0.0.1:9001;
 keepalive 64;
    }

    server {
 listen 443 ssl http2;
 # Iets langer idle-venster voor terugkerende verzoeken
 http2_idle_timeout 75s;
    }
}

Checklist voor iteratieve optimalisatie

Ik begin met een analyse van de huidige situatie: verkeerspatronen, responstijden en foutpercentages bepalen het tempo. Vervolgens stel ik de client-time-out en het aantal verzoeken per gebruiker in op solide startwaarden en activeer ik de upstream-pools. De backend-idle-time-outs stel ik iets hoger in dan bij NGINX, zodat er geen onverwachte Resets voorkomen. Vervolgens houd ik de verbindingssnelheden, de connect-tijd en het aantal open sockets per worker in de gaten. Wie zich verder wil verdiepen in de mate van hergebruik, vindt hier suggesties over Aansluiting Hergebruik en redelijke bovengrenzen.

Aanvullende diagnose: mismatches en tijdsgedrag

Als verbindingen schijnbaar „zonder reden“ worden verbroken, ga ik op zoek naar Mismatches in de keten: Client-Idle versus NGINX-time-out versus Backend-Idle en tussenliggende NAT/gateways. Ik verhoog de backend-time-out iets boven de NGINX-waarde, controleer de resetcodes in het foutenlogboek en kijk of stroomopwaartse_verbindingstijd pieken vertoont. Vaak volstaat een kleine buffer (bijv. +10–20%) bij de backend-time-out om resets te voorkomen.

Ik merk bovendien op dat „langdurige omhelzing“-Fasen: Bij het sluiten laat NGINX inkomende gegevens kort doorlopen, wat worker-bronnen in beslag neemt. Een groot aantal gelijktijdige sluitingen kan events blokkeren. In dergelijke gevallen pas ik de sluitingsvensters aan en houd ik het totale aantal open verbindingen in evenwicht door zinvolle keepalive-waarden in te stellen.

Samenvatting: Keepalive als middel om de prestaties te verbeteren

Ik maak doelgericht gebruik van Keepalive, omdat het de kosten voor het opbouwen van verbindingen verlaagt, de latentie vermindert en de CPU ontlast. De combinatie van een geschikte time-out, een strakke limiet voor verzoeken en geschikte upstream-pools levert merkbare Snelheid. Zonder monitoring blijft potentieel onbenut; daarom controleer ik de kengetallen voortdurend en pas ik de waarden stap voor stap aan. Wie extra reserves nodig heeft, let op het aantal workers, de verbindingsslots en de juiste verwerking van headers. Professionele configuraties, bijvoorbeeld bij webhoster.de, maken optimaal gebruik van deze mogelijkheden en leveren snelle, betrouwbare diensten.

Huidige artikelen

Technische serverinfrastructuur met de nadruk op Linux NUMA-analyse
Servers en virtuele machines

Linux NUMA-statistieken correct interpreteren

Linux NUMA-statistieken correct analyseren: NUMA-statistieken begrijpen, geheugenlokalisatie controleren en de serverprestaties doelgericht verbeteren.