Med nginx sendfile och tcp_nopush Jag levererar statiska filer med ”zero-copy” från filsystemet till socketen och minskar därmed märkbart både CPU-belastningen och antalet paket. Om de är korrekt inställda ökar båda direktiven överföringseffektiviteten, minskar overheaden och lägger grunden för en smidig nginx-optimering av tillgångar och nedladdningar.
Centrala punkter
- Nollkopia med sendfile: färre kopior, högre genomströmning
- tcp_nopush buffrar paket: större ramar, mindre overhead
- Kombination räknas: sendfile + tcp_nopush + tcp_nodelay
- Användningsfall prioritera: statiska tillgångar, stora nedladdningar
- Tester för NFS/SMB: Mäta effekten, stäng av sendfile vid behov
Varför sendfile frigör så mycket prestanda för NGINX
Jag aktiverar sendfile, eftersom kärnan kan skicka filer direkt via nätverksstacken utan att behöva ta en omväg via ytterligare kopieringsoperationer i användarutrymmet. Denna ”zero-copy”-väg minskar antalet kontextbyten och sparar CPU-cykler, särskilt när många klienter samtidigt hämtar statiskt innehåll. Stora filer som bilder, CSS, JavaScript eller arkiv gynnas eftersom dataöverföringen sker jämnare och med mindre overhead. Även systemcacherna fungerar effektivare eftersom färre minnesflyttningar sker och kärnan styr dataströmmen. På lokala filsystem är vinsten tydligast, vilket är anledningen till att jag först mäter där innan jag överför resultaten till mer exotiska konfigurationer.
Vad tcp_nopush egentligen gör och när det kommer till sin rätt
Med tcp_nopush Jag ber systemet att först skicka TCP-paket när de är fullt fyllda, istället för att skicka små segment för tidigt. Under Linux motsvarar detta TCP_CORK, under FreeBSD TCP_NOPUSH, och i båda fallen minskar antalet paket märkbart. Direktivet minimerar inte latensen, utan syftar till ett bättre förhållande mellan nyttodata och overhead. Jag använder tcp_nopush specifikt för statiska filer, eftersom sammanhängande dataströmmar där ger störst effektivitetsvinster. Utan sendfile har tcp_nopush ingen effekt, därför aktiverar jag alltid båda inställningarna tillsammans.
sendfile och tcp_nopush i kombination: så här lägger jag grunden
Kombinationen av sendfile och tcp_nopush minskar antalet kopior och grupperar paket, vilket gör att en server per CPU-kärna kan hantera betydligt fler parallella överföringar. Jag konfigurerar båda på http-kontextnivån och lägger ofta till tcp_nodelay så att den sista delen av ett flöde kan skickas utan väntetid. Det är fortfarande viktigt att testa med verklig trafik, eftersom paketstorlekar, MTU och klienter varierar och den bästa balansen kan skilja sig något beroende på arbetsbelastningen. För statiska kataloger räcker det oftast med global aktivering, medan jag vid dynamiska svarsvägar håller ett öga på effekten. Denna kombination ger en solid grund för ytterligare nginx-optimeringsåtgärder som läggs till senare.
| direktiv | Syfte | Typiska effekter | Beroende |
|---|---|---|---|
| sendfile på | Zero-Copy från fil till socket | Mindre belastning på processorn, högre genomströmning | Ett lokalt filsystem är idealiskt |
| tcp_nopush på | Fylla paket, sänka omkostnaderna | Färre segment per fil | Fungerar endast med sendfile |
| tcp_nodelay on | Skicka de sista byte utan att vänta | Snabb avslutning av överföringen | Kompletterar tcp_nopush |
Så här samverkar tcp_nodelay med tcp_nopush
Jag aktiverar tcp_nopush, för att skicka början av en överföring i större paket, och tillåter samtidigt tcp_nodelay så att avslutningen inte fastnar. Båda inställningarna påverkar olika faser i flödet och stör inte varandra när NGINX levererar filer via sendfile. Särskilt vid många små filer förhindrar tcp_nodelay att klienten väntar i onödan på grund av små mängder återstående data. Jag testar kombinationen först i staging-miljön, observerar RTT:er och segmentstorlekar och jämför dem med live-metriker. På så sätt säkerställer jag effektivitet i början och snabbhet i slutet av överföringen.
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}
Typiska användningsscenarier: där direktiven har stor inverkan
Vid stora Nedladdningar Precis som för videor, arkiv eller ISO-avbildningar minskar kärnans Zero-Copy-väg CPU-tiden per överföring avsevärt. I CDN-liknande konfigurationer med många CSS-, JS- och teckensnittsfiler sparar tcp_nopush segment och ökar därmed den användbara bandbredden per socket. På WordPress-sidor med bra caching gäller de flesta förfrågningarna statiska tillgångar, vilket gör att jag ser effekten där mycket snabbt. Även byggartefakter, containerbilder eller installationsprogram drar nytta av detta, förutsatt att de finns lokalt och inte kommer via ett instabilt nätverksfilsystem. Den som förväntar sig belastningstoppar får med denna kombination ut mycket stabilitet ur den befintliga hårdvaran.
Praktiskt exempel: NGINX för WordPress med caching och tillgångar
I WordPress-installationer använder jag sendfile, tcp_nopush och tcp_nodelay globalt, levererar statiska resurser direkt och håller PHP-FPM för dynamiska sökvägar tydligt åtskilda. Jag lägger till meningsfulla cache-headers för bilder, CSS och JavaScript så att webbläsarna orsakar färre rundresor. När jag levererar strömningsliknande svar tar jag hänsyn till interaktionen med buffring och testar hur chunkstorlekar påverkar latens och genomströmning; detta passar bra ihop med översikten över Svarsströmning i bitar. För textbaserat innehåll använder jag komprimering utan att packa binärfiler i onödan. På så sätt förblir begärandeflödet stabilt, CPU:n belastas inte för mycket och tiden till första byte blir kort.
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
gzip_types text/css application/javascript image/svg+xml;
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg|woff2?)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
}
}
När jag medvetet inaktiverar sendfile
Jag byter sendfile om filerna ligger på NFS, SMB eller distribuerade filsystem, som i mitt test ger sämre genomströmning. Vissa drivrutiner eller fördröjningar i lagringsvägen kan upphäva fördelarna med zero-copy, varför mätningar är avgörande. Vid sporadiska nätverksproblem stänger jag först av tcp_nopush för att avgränsa effekterna innan jag ifrågasätter sendfile i sig. Även ovanliga kärnbuggar eller äldre stackar kan vara skäl att tillfälligt byta till den klassiska läs- och skrivvägen. Det är viktigt att införa ändringar stegvis och underbygga dem med mätvärden.
Felkällor som jag håller koll på
Jag kontrollerar först om tcp_nopush är aktiverad av misstag medan sendfile är avstängd, eftersom inställningen då inte har någon effekt. När det gäller dynamiska sökvägar observerar jag om ytterligare buffringar ökar latensen och väger fördelarna mot svarstiden. I nätverk med hög latens mäter jag om större paket verkligen hjälper eller om jag behöver finjustera segmentstorlekar och keep-alive. Även MTU-konfigurationen och nätverkskortets avlastningsfunktioner kan märkbart påverka resultatet. Tydliga loggar, pcap-prov och korrelerade systemmetriker visar mig snabbt var jag behöver justera.
Att tänka helhetsmässigt kring NGINX-prestanda: ytterligare justeringsmöjligheter
Förutom sendfile Det lönar sig att ange rätt antal worker_processes och worker_connections, så att jag inte begränsar antalet socklar på konstgjord väg. Under Linux använder jag epoll och ser till att det finns tillräckligt med filbeskrivare, så att belastningstoppar inte leder till flaskhalsar. För textinnehåll aktiverar jag gzip eller Brotli och testar om komprimeringsnivån belastar processorn på ett rimligt sätt. På transportnivån håller jag anslutningarna öppna längre och optimerar Keep-Alive, vilket beskrivs i handledningen Keep-Alive-inställning ger praktiska riktlinjer. TLS, återanvändning av sessioner samt HTTP/2 eller HTTP/3 kompletterar konfigurationen och möjliggör hög parallellitet med måttlig latens.
Begränsningar och specialfall: TLS, HTTP/2/3 och proxyserveranvändning
Jag tar hänsyn till att sendfile tekniskt sett endast gäller för okrypterade filvägar eller särskilda kärnfunktioner. Vid klassisk TLS krypterar NGINX byten i användarutrymmet, varför fördelen med zero-copy går förlorad; moderna kärnor kan delvis flytta krypteringen till kärnan, vilket återställer effekten, men detta är inte tillgängligt i alla konfigurationer. Vid HTTP/2 Om data finns i ramar, flera svar delar på en TCP-anslutning och NGINX ompaketerar aktivt byten – då är sendfile mindre relevant. HTTP/3 baseras på UDP/QUIC och följer återigen andra regler, vilket innebär att jag snarare uppnår effektivitetsvinster genom buffertar, överbelastningskontroll och korrekt valda chunkstorlekar. Som Omvänd proxy sendfile träder endast i kraft när jag faktiskt serverar filer från det lokala filsystemet; svar från proxy_pass eller . fastcgi_pass går ändå via användarutrymmet. Därför separerar jag tillgångarna strikt från den dynamiska sökvägen, så att Zero-Copy-metoden utnyttjas maximalt.
Att förstå komprimering på rätt sätt: gzip/Brotli kontra gzip_static
När NGINX komprimerar innehåll i realtid måste det läsa filen, bearbeta den och skriva ut resultatet – och då går sendfile sin fördel. För statiska tillgångar använder jag därför, där det är möjligt, förkomprimerade Filer (t.ex. .gz eller .br) och låter dem levereras direkt. På så sätt bibehålls Zero-Copy-vägen, eftersom NGINX kan vidarebefordra den förkomprimerade filen precis som vilken annan resurs som helst. För textintensivt innehåll som sällan ändras uppnår jag på så sätt CPU-besparingar och stabil genomströmning utan att förlora överföringstid. När det gäller binära filer och redan komprimerade format slipper jag all komprimering under körning – här är det ren I/O-genomströmning som räknas, och sendfile plus tcp_nopush visar sina styrkor.
AIO, directio och sidcache: mönster för små och stora filer
Jag kombinerar sendfile med asynkron I/O och direkt diskåtkomst för att uppnå bästa möjliga resultat beroende på filstorlek. Små till medelstora filer drar nytta av kärnans sidcache och förblir på sendfile-vägen. Mycket stora filer kan däremot tränga undan cachen; då läser jag dem specifikt med direktiv utanför cachen och arbetar med AIO-trådar. På så sätt avlastar jag minnet och håller latensen låg för andra förfrågningar. Ett typiskt mönster ser ut så här:
http {
# Standardväg: Zero-Copy från sidcachen
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Stora filer: förbi cachen och asynkron läsning
aio threads;
directio 4m; # gäller endast för filer >= 4 MiB
output_buffers 1 512k; # Buffert för directio-vägar
sendfile_max_chunk 1m; # Jämn belastning vid hög belastning
}
Med denna gradering förblir små tillgångar extremt effektiva, samtidigt som mycket stora överföringar inte överbelastar arbetsminnet. Viktigt: directio inaktiverar sendfile-vägen för berörda filer – precis som jag avser att göra för användningsfallet med stora filer.
Rättvisa och flödeskontroll under belastning
Under perioder med hög belastning vill jag undvika att en enda ström monopoliserar processorn eller sockeln. Jag använder sendfile_max_chunk, så att NGINX returnerar kärnan efter en definierad mängd byte och ger utrymme åt andra anslutningar. För bandbreddshantering är följande till hjälp limit_rate och limit_rate_after, till exempel för att begränsa massnedladdningar samtidigt som UI-resurserna förblir snabba. Med postpone_output Jag styr vid vilken svarsstorlek NGINX börjar skicka – i kombination med tcp_nopush ser jag därmed till att paketdelningen blir ren. Dessutom ser jag till att lingering_close, så att återstående paket kan skickas vidare på ett korrekt sätt och att anslutningen inte avslutas abrupt.
Filsystem, readahead och lagringsvägar
Därför att sendfile När man använder sidcacher spelar det underliggande filsystemet en viktig roll. Jag kontrollerar readahead-värdena och justerar dem så att sekventiella läsoperationer av stora filer inte avstannar, utan att mindre resurser trängs undan. På ext4 eller . xfs Jag observerar hur väl prefetching och I/O-schemaläggaren harmonierar med mitt genomströmningsmönster. På nätverksfilsystem (NFS/SMB) testar jag rsize/wsize, caching och latenser noggrant, eftersom även små avvikelser neutraliserar fördelarna med zero-copy. Min regel är fortfarande: utnyttja först de lokala sökvägarna maximalt, justera sedan de externa stackarna försiktigt – och låt alltid mätvärdena gå före magkänslan.
Pragmatisk anpassning av nätverksstacken och NIC-avlastning
Vid ett stort antal anslutningar förlitar jag mig på den automatiska buffertjusteringen i moderna stackar, men justerar sändnings- och mottagningsbuffertarna vid behov. NIC-avlastningar som TSO, GSO och GRO minskar CPU-belastningen märkbart; vid mätningar är jag dock försiktig, eftersom paketfångster kan förvrängas av avlastningen (till synes få, mycket stora segment). Därför korrelerar jag pcap‑Spår med mätvärden från NGINX och kärnan för att skilja verkliga trådstorlekar från avlastningsartefakter. Vid latensspikar avbryter jag testerna kortvarigt med avlastningen inaktiverad, dokumenterar skillnaden och avgör sedan vad som ger störst nytta vid kontinuerlig drift.
Konfigurationsmallar per plats: aktivera och inaktivera selektivt
Jag håller dörren öppen för att, sendfile att skriva över beroende på sökväg eller filtyp. För statiska kataloger förblir den aktiverad, medan jag för strömmande eller dynamiska sökvägar inaktiverar den selektivt när buffertar eller filter (t.ex. komprimering) har företräde. Ett kort exempel:
server {
listen 80;
server_name static.example.com;
root /var/www/static;
# Statiska resurser: Zero-Copy
location /assets/ {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
expires 7d;
}
# Dynamiskt innehåll eller streaming: Flexibilitet före Zero-Copy
location /api/ {
sendfile off;
proxy_pass http://app_upstream;
}
}
Denna åtskillnad förhindrar att jag går miste om fördelar på den ena sidan, bara för att en annan väg ställer särskilda krav.
Range, Slices och stora kataloger
Vid stora objekt gäller följande Räckvidd-förfrågningar utnyttjar sina styrkor: Klienten laddar endast nödvändiga delar, och anslutningarna förblir stabila. I innehållskataloger med mycket stora filer segmenterar jag gärna överföringarna logiskt – serverbelastningen fördelas jämnare, och fel som avbrott tar mindre tid. I cachelagringsscenarier förebygger jag „Thundering Herds“ genom att buffra svar på ett meningsfullt sätt, men utan att artificiellt hålla kvar små delar och återstående data. Samspelet med tcp_nopush är centralt i detta sammanhang: jag håller inledande segment stora, men låter inte slutet vänta.
Mät- och teststrategi: Pålitligt påvisa effekter
Jag underbygger optimeringarna med reproducerbara tester. På serversidan övervakar jag CPU-profiler, 1TP4Begäran_tid, 1 TP 4 Tbyte skickade, aktiva anslutningar och kontextbyten. I nätverket mäter jag segmentstorlekar, återutsändningar och RTT-fördelning; jag korrelerar paketfångster med socket-statistik för att ta hänsyn till avlastningseffekter. På klientsidan jämför jag TTFB, First Contentful Paint och nedladdningstider under realistiska RTT-värden och bandbredder. Jag varierar MTU, Keep-Alive-inställningar och filstorlekar så att jag inte bara ser kurvor för bästa tänkbara fall. Till slut avgör jag utifrån konkreta siffror om sendfile/tcp_nopush ger önskad stabilitet och effektivitet i den aktuella arbetsbelastningen – och finjusterar tills de gör det.
HTTP-detaljer som gör skillnad: Range och streaming
Jag använder Räckvidd-Begäranden vid stora filer, så att klienterna endast laddar ner nödvändiga delar och anslutningarna förblir stabila. Särskilt vid videoförskjutningar och återupptagna uppdateringar bidrar ett välfungerande stöd för byteintervall till att fördelningen av genomströmningen sker på ett effektivt sätt; bakgrundsinformation finns på sidan om HTTP-Range-förfrågningar. För löpande svar med växande innehåll testar jag strömningsstrategier och ser till att buffertarna inte oavsiktligt behåller data för länge. Samtidigt tar jag hänsyn till cacher och anger lämpliga rubriker så att proxyservrar och webbläsare fungerar korrekt. Jag tar hänsyn till samspelet med tcp_nopush, eftersom paketstorlekar och tidpunkten för tömningen har direkt inverkan på den upplevda hastigheten.
Kortfattat sammanfattat
Med sendfile Jag vidarebefordrar filer effektivt direkt till kärnan, och med tcp_nopush ser jag till att paketen fylls på ett lämpligt sätt innan de belastar linjen. Dessa båda direktiv kompletterar varandra, medan tcp_nodelay levererar den sista byte-resten utan fördröjning. Jag testar effekten under verklig trafik, håller koll på lagringsvägen, MTU, Keep-Alive och komprimering och mäter noggrant. För WordPress- och CDN-liknande arbetsbelastningar blir nyttan särskilt snabbt tydlig, eftersom många förfrågningar gäller statiska resurser. Den som använder inställningarna på ett målinriktat sätt uppnår högre genomströmning per kärna, minskar overhead och skapar reserver för verkliga tillväxttoppar.


