Checklist Essenziale per l'Ottimizzazione delle Prestazioni di Nginx per Siti Web ad Alto Traffico
Una checklist pratica per le prestazioni di Nginx riguardante worker, connessioni, buffer, caching, compressione, log, timeout, TLS e file statici.
Checklist Essenziale per l'Ottimizzazione delle Prestazioni di Nginx per Siti Web ad Alto Traffico
L'ottimizzazione delle prestazioni di Nginx è più semplice quando la si tratta come una checklist, non come un gioco di ipotesi. Inizia con i limiti che determinano quanto traffico Nginx può accettare, poi passa al buffering, caching, compressione, logging, timeout, TLS e ai servizi backend che lo supportano.
Non applicare tutte queste direttive in produzione contemporaneamente. Una buona checklist per l'ottimizzazione delle prestazioni di Nginx ti aiuta a decidere cosa controllare, perché è importante e cosa può andare storto se si esagera. L'impostazione giusta per un sito di documentazione prevalentemente statico non è la stessa per un'API con long-polling o un servizio di upload file.
1. Ottimizza i Processi Worker e le Connessioni
Nginx sfrutta un modello di processo master-worker. Il processo master legge la configurazione e gestisce i processi worker, che gestiscono le richieste effettive dei client. Configurarli correttamente può migliorare drasticamente la concorrenza e l'utilizzo delle risorse.
worker_processes
Questa direttiva determina quanti processi worker Nginx avvierà. Generalmente, impostarlo su auto permette a Nginx di rilevare il numero di core CPU e avviare un numero uguale di processi worker, che è una pratica comune.
worker_connections
Definisce il numero massimo di connessioni simultanee che un singolo processo worker può aprire. Questa impostazione, insieme a worker_processes, determina il totale teorico di connessioni concorrenti che Nginx può gestire (worker_processes * worker_connections).
multi_accept
Consente a un processo worker di accettare più nuove connessioni contemporaneamente, prevenendo potenziali colli di bottiglia sotto carico elevato.
# /etc/nginx/nginx.conf
worker_processes auto; # Di solito impostato su 'auto' o sul numero di core CPU
events {
worker_connections 1024; # Regola in base alla capacità del server e al carico previsto
multi_accept on;
}
Suggerimento: Se la CPU è costantemente alta, aumentare
worker_connectionsnon risolverà il problema da solo. Prima verifica se la CPU è causata da handshake TLS, compressione, logging, routing basato su regex pesanti o dall'applicazione upstream.
2. Gestione Efficiente delle Connessioni
Ottimizzare come Nginx gestisce le connessioni di rete può ridurre il sovraccarico e migliorare la reattività.
keepalive_timeout
Specifica per quanto tempo una connessione keep-alive del client rimarrà aperta. Riutilizzare le connessioni riduce il sovraccarico di stabilire nuove connessioni TCP e handshake SSL. Un valore comune è 15-65 secondi, a seconda dell'interattività dell'applicazione.
sendfile
Abilita il trasferimento diretto dei dati tra descrittori di file, bypassando il buffering nello spazio utente. Questo migliora significativamente le prestazioni quando si servono file statici.
tcp_nopush
Funziona con sendfile. Nginx cerca di inviare l'intestazione HTTP e l'inizio del file in un unico pacchetto. Successivamente, invia i dati in pacchetti completi. Questo riduce il numero di pacchetti inviati.
tcp_nodelay
Indica a Nginx di inviare i dati non appena sono disponibili, senza bufferizzare. Questo è vantaggioso per applicazioni interattive dove la bassa latenza è più critica della massimizzazione del throughput (es. applicazioni chat o aggiornamenti in tempo reale).
http {
keepalive_timeout 65; # Connessioni keep-alive per 65 secondi
sendfile on;
tcp_nopush on; # Richiede sendfile on
tcp_nodelay on; # Utile per il proxy di contenuti dinamici
}
3. Ottimizzazione dei Buffer
Nginx utilizza buffer per gestire le richieste dei client e le risposte dai server upstream (come i server applicativi). Dimensionare correttamente questi buffer può prevenire I/O su disco non necessari, ridurre l'uso della memoria e migliorare il throughput.
Buffer del Client
client_body_buffer_size: Dimensione del buffer per i corpi delle richieste dei client. Se un corpo supera questa dimensione, viene scritto in un file temporaneo.client_header_buffer_size: Dimensione del buffer per la prima riga e le intestazioni di una richiesta del client.large_client_header_buffers: Definisce il numero e la dimensione di buffer più grandi per leggere le intestazioni delle richieste dei client. Utile per richieste con molti cookie o intestazioni referer lunghe.
Buffer Proxy (per configurazioni reverse proxy)
proxy_buffers: Il numero e la dimensione dei buffer utilizzati per leggere le risposte dal server proxy.proxy_buffer_size: La dimensione del primo buffer per leggere la risposta. Tipicamente più piccolo, poiché spesso contiene solo intestazioni.proxy_busy_buffers_size: La quantità massima di buffer di risposta che possono essere nello stato 'busy' (in fase di invio al client) in un dato momento.
Buffer FastCGI (per PHP-FPM, ecc.)
fastcgi_buffers: Il numero e la dimensione dei buffer utilizzati per leggere le risposte dal server FastCGI.fastcgi_buffer_size: La dimensione del primo buffer per leggere la risposta.
http {
# Buffer del Client
client_body_buffer_size 1M; # Regola in base alla dimensione prevista del corpo della richiesta (es. upload file)
client_header_buffer_size 1k;
large_client_header_buffers 4 8k; # 4 buffer, ciascuno da 8KB
# Buffer Proxy (se Nginx agisce come reverse proxy)
proxy_buffers 8 16k; # 8 buffer, ciascuno da 16KB
proxy_buffer_size 16k; # Primo buffer da 16KB
proxy_busy_buffers_size 16k; # Max 16KB di buffer busy
# Buffer FastCGI (se Nginx lavora con PHP-FPM)
fastcgi_buffers 16 16k; # Punto di partenza per molte app PHP-FPM
fastcgi_buffer_size 16k; # Primo buffer da 16KB
}
Attenzione: Impostare buffer troppo piccoli può portare a I/O su disco e degrado delle prestazioni. Impostarli troppo grandi può consumare memoria eccessiva. Trova un equilibrio attraverso i test.
4. Implementa Strategie di Caching Robuste
Il caching è uno dei modi più efficaci per migliorare le prestazioni e ridurre il carico sui server backend. Nginx può fungere da potente cache di contenuti.
proxy_cache_path
Definisce il percorso della directory della cache, la sua dimensione, il numero di livelli di sottodirectory e per quanto tempo gli elementi inattivi rimangono nella cache.
proxy_cache
Attiva il caching per un dato blocco location, facendo riferimento alla zona definita in proxy_cache_path.
proxy_cache_valid
Imposta il tempo per cui Nginx deve memorizzare nella cache le risposte con specifici codici di stato HTTP.
proxy_cache_revalidate
Quando abilitato, Nginx utilizzerà le intestazioni If-Modified-Since e If-None-Match per riconvalidare il contenuto cache con il backend, riducendo l'uso della larghezza di banda.
proxy_cache_use_stale
Indica a Nginx di servire contenuto cache obsoleto se il server backend è giù, non risponde o sta riscontrando errori. Questo migliora notevolmente la disponibilità.
expires
Imposta le intestazioni Cache-Control e Expires per il caching lato client di file statici. Questo minimizza le richieste ripetute a Nginx.
http {
# Definisci una zona cache proxy nel blocco http
proxy_cache_path /var/cache/nginx/my_cache levels=1:2 keys_zone=my_cache:10m inactive=60m max_size=10g;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://my_upstream_backend;
proxy_cache my_cache; # Abilita il caching per questa location
proxy_cache_valid 200 302 10m; # Memorizza nella cache le risposte di successo per 10 minuti
proxy_cache_valid 404 1m; # Memorizza nella cache i 404 per 1 minuto
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status; # Aiuta con il debugging
}
# Memorizza nella cache i file statici nel browser per un periodo più lungo
location ~* \.(jpg|jpeg|gif|png|css|js|ico|woff|woff2|ttf|svg|eot)$ {
expires 30d; # Cache per 30 giorni
add_header Cache-Control "public, no-transform";
# Per file statici, considera di servirli direttamente da Nginx se non proxy
root /var/www/html;
}
}
}
5. Abilita la Compressione Gzip
Comprimere le risposte prima di inviarle ai client può ridurre significativamente l'uso della larghezza di banda e migliorare i tempi di caricamento delle pagine, specialmente per contenuti testuali.
gzip on
Attiva la compressione gzip.
gzip_comp_level
Imposta il livello di compressione (1-9). Il livello 1 è il più veloce con meno compressione; il livello 9 è il più lento con la massima compressione. Il livello 6 offre di solito un buon equilibrio.
gzip_types
Specifica i tipi MIME che devono essere compressi. Includi tipi comuni di testo, CSS, JavaScript e JSON.
gzip_min_length
Imposta la lunghezza minima di una risposta (in byte) per cui abilitare la compressione. I file piccoli non beneficiano molto e potrebbero persino essere più lenti a causa del sovraccarico della compressione.
gzip_proxied
Indica a Nginx di comprimere le risposte anche se sono proxy. any è un valore comune.
gzip_vary
Aggiunge l'intestazione Vary: Accept-Encoding alle risposte, informando i proxy che la risposta può differire in base all'intestazione della richiesta Accept-Encoding.
http {
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6; # Livello di compressione 1-9 (6 è un buon equilibrio)
gzip_buffers 16 8k; # 16 buffer, ciascuno da 8KB
gzip_http_version 1.1; # Versione HTTP minima per la compressione
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1000; # Comprimi solo risposte più grandi di 1KB
}
6. Ottimizza il Logging
Mentre i log sono essenziali per il monitoraggio e la risoluzione dei problemi, un logging eccessivo o non ottimizzato può introdurre un I/O su disco significativo, specialmente su siti ad alto traffico.
access_log
- Disabilita per asset statici: Per contenuti statici molto accessati (immagini, CSS, JS), disabilitare
access_logpuò risparmiare molto I/O. - Buffering: Nginx può bufferizzare le voci di log in memoria prima di scriverle su disco, riducendo la frequenza delle scritture su disco. I parametri
buffereflushvengono utilizzati qui.
error_log
Imposta il livello di logging appropriato (crit, error, warn, info, debug). Per la produzione, warn o error è di solito sufficiente per catturare problemi critici senza inondare i log.
http {
server {
# Log di accesso predefinito per contenuti dinamici
access_log /var/log/nginx/access.log main;
location ~* \.(jpg|jpeg|gif|png|css|js|ico|woff|woff2|ttf|svg|eot)$ {
access_log off; # Disabilita il logging per file statici comuni
expires 30d;
}
}
# Esempio di log di accesso bufferizzato per il contesto HTTP principale
# access_log /var/log/nginx/access.log main buffer=16k flush=5s;
error_log /var/log/nginx/error.log warn; # Logga solo warning e superiori
}
7. Regola i Timeout
Timeout configurati correttamente impediscono a Nginx di mantenere connessioni inattive troppo a lungo, liberando risorse.
Timeout Lato Client
client_body_timeout: Quanto tempo Nginx aspetta che un client invii il corpo della richiesta.client_header_timeout: Quanto tempo Nginx aspetta che un client invii l'intestazione della richiesta.send_timeout: Quanto tempo Nginx aspetta che un client accetti la risposta dopo che è stata inviata.
Timeout Proxy/FastCGI (se applicabile)
proxy_connect_timeout: Timeout per stabilire una connessione con un server proxy.proxy_send_timeout: Timeout per trasmettere una richiesta al server proxy.proxy_read_timeout: Timeout per leggere una risposta dal server proxy.
http {
client_body_timeout 15s; # Il client ha 15 secondi per inviare il corpo
client_header_timeout 15s; # Il client ha 15 secondi per inviare le intestazioni
send_timeout 15s; # Nginx ha 15 secondi per inviare la risposta al client
# Per scenari proxy
proxy_connect_timeout 5s; # 5 secondi per connettersi all'upstream
proxy_send_timeout 15s; # 15 secondi per inviare la richiesta all'upstream
proxy_read_timeout 15s; # 15 secondi per leggere la risposta dall'upstream
# Per scenari FastCGI
fastcgi_connect_timeout 5s;
fastcgi_send_timeout 15s;
fastcgi_read_timeout 15s;
}
8. Ottimizzazione SSL/TLS
Per i siti abilitati HTTPS, ottimizzare le impostazioni SSL/TLS è cruciale per ridurre il sovraccarico della CPU e migliorare le prestazioni dell'handshake.
ssl_session_cache e ssl_session_timeout
Abilita la memorizzazione nella cache delle sessioni SSL per evitare il costoso handshake TLS completo per connessioni successive dallo stesso client.
ssl_protocols e ssl_ciphers
Usa protocolli TLS moderni come TLSv1.2 e TLSv1.3. Fai attenzione con stringhe di cifratura copiate: le cifrature TLS 1.3 non sono controllate allo stesso modo delle suite di cifratura TLS più vecchie, e le impostazioni predefinite della distribuzione sono spesso più sicure di esempi obsoleti da guide vecchie.
ssl_stapling
Abilita OCSP stapling, dove Nginx recupera periodicamente la risposta OCSP dalla CA e la "cucina" all'handshake SSL/TLS. Questo riduce la latenza lato client evitando una query OCSP separata.
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/your_domain.crt;
ssl_certificate_key /etc/nginx/ssl/your_domain.key;
ssl_session_cache shared:SSL:10m; # Cache condivisa per 10MB di dati di sessione
ssl_session_timeout 10m; # Le sessioni scadono dopo 10 minuti
ssl_protocols TLSv1.2 TLSv1.3; # Usa protocolli moderni e sicuri
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s; # Usa resolver approvati per il tuo ambiente
resolver_timeout 5s;
}
9. Cache dei File Aperti
Nginx può memorizzare nella cache i descrittori di file per file frequentemente accessati, riducendo la necessità di chiamate di sistema ripetute per aprire e chiudere file.
open_file_cache
Abilita la cache, specificando il numero massimo di elementi e per quanto tempo gli elementi inattivi rimangono.
open_file_cache_valid
Imposta la frequenza con cui la cache deve verificare la validità dei suoi elementi.
open_file_cache_min_uses
Specifica il numero minimo di volte che un file deve essere accessato entro il tempo inactive per rimanere nella cache.
open_file_cache_errors
Determina se Nginx deve memorizzare nella cache gli errori quando apre i file.
http {
open_file_cache max=100000 inactive=60s; # Cache fino a 100.000 descrittori di file per 60s
open_file_cache_valid 80s; # Verifica la validità ogni 80 secondi
open_file_cache_min_uses 1; # Cache dei file usati almeno una volta
open_file_cache_errors on; # Cache degli errori relativi all'apertura dei file
}
10. Convalida con Segnali di Traffico Reali
L'ultimo elemento della checklist è la misurazione. Prima di una modifica, cattura una piccola baseline: latenza delle richieste, tasso di 5xx, connessioni attive, CPU, memoria, I/O su disco, throughput di rete e tempo di risposta upstream. Dopo la modifica, confronta gli stessi numeri.
Per un reverse proxy, $request_time e $upstream_response_time sono particolarmente utili. Se entrambi aumentano insieme, probabilmente il backend è lento. Se $request_time è alto mentre il tempo upstream è basso o vuoto, guarda la velocità di upload del client, il tempo di trasferimento della risposta, il buffering, la compressione o la consegna di file statici. Se nessuna metrica spiega il problema, controlla il log degli errori e il sistema operativo.
La sequenza di ottimizzazione più sicura è semplice: testa la configurazione con nginx -t, ricarica invece di riavviare quando possibile, monitora i log e torna indietro rapidamente se la latenza o gli errori vanno nella direzione sbagliata. Nginx può gestire molto traffico, ma solo quando i suoi limiti, il kernel e l'applicazione upstream sono d'accordo tra loro.