- Home
- Simulatore CDN
- Configurazione NGINX
Configurazione NGINX
Il provisioning cloud-init distribuisce una configurazione NGINX per CDN edge completamente ottimizzata per le prestazioni. Questa pagina documenta ogni livello di configurazione, dall’ottimizzazione del kernel al comportamento della cache fino all’iniezione degli header dei vendor. Tutte le impostazioni sono state verificate durante un test di carico continuo di 48 ore con un picco di 172.540 req/s.
File di Configurazione
Sezione intitolata “File di Configurazione”| File | Scopo |
|---|---|
/etc/sysctl.d/99-cdn-tuning.conf | Ottimizzazione della rete del kernel Linux |
/etc/systemd/system/nginx.service.d/override.conf | Limiti dei descrittori di file per NGINX |
/etc/security/limits.d/99-nginx.conf | Limiti a livello di OS per l’utente www-data |
/etc/nginx/nginx.conf | Configurazione principale NGINX (worker, buffer, gzip, logging) |
/etc/nginx/conf.d/cdn-edge.conf | Configurazione proxy CDN (cache, upstream, header) |
Ottimizzazione del Kernel
Sezione intitolata “Ottimizzazione del Kernel”Applicata tramite /etc/sysctl.d/99-cdn-tuning.conf all’avvio.
| Parametro | Valore | Default | Scopo |
|---|---|---|---|
net.core.somaxconn | 65535 | 4096 | Dimensione della coda di backlog in ascolto |
net.core.netdev_max_backlog | 65535 | 1000 | Backlog dei pacchetti in ingresso per CPU |
net.ipv4.tcp_max_syn_backlog | 65535 | 256 | Coda delle richieste SYN (previene perdite sotto burst) |
net.ipv4.tcp_tw_reuse | 1 | 2 | Riutilizza i socket TIME_WAIT per le connessioni in uscita |
net.ipv4.ip_local_port_range | 1024-65535 | 32768-60999 | Range delle porte effimere (64K vs 28K) |
net.core.rmem_max | 16 MB | 212 KB | Buffer socket di ricezione massimo |
net.core.wmem_max | 16 MB | 212 KB | Buffer socket di invio massimo |
net.ipv4.tcp_rmem | 4K/87K/16M | 4K/131K/6M | Buffer di ricezione per socket (min/default/max) |
net.ipv4.tcp_wmem | 4K/65K/16M | 4K/16K/4M | Buffer di invio per socket (min/default/max) |
net.ipv4.tcp_fin_timeout | 15 | 60 | Timeout FIN_WAIT_2 (pulizia più rapida dei socket) |
net.ipv4.tcp_keepalive_time | 300 | 7200 | Avvia le probe keepalive dopo 5 min di inattività |
net.ipv4.tcp_slow_start_after_idle | 0 | 1 | Mantiene la finestra di congestione attiva sulle connessioni inattive |
net.ipv4.tcp_max_tw_buckets | 2000000 | ~65536 | Numero massimo di socket TIME_WAIT |
fs.file-max | 2097152 | variabile | Limite di descrittori di file a livello di sistema |
vm.swappiness | 10 | 60 | Preferisce la RAM allo swap per i dati di cache |
Configurazione Principale NGINX
Sezione intitolata “Configurazione Principale NGINX”Worker e Connessioni
Sezione intitolata “Worker e Connessioni”worker_processes auto; # 4 worker su D4s_v5 (1 per vCPU)worker_rlimit_nofile 65535; # Limite descrittori di file per worker
events { use epoll; # Modello di eventi ottimizzato per Linux worker_connections 8192; # 4 worker x 8192 = 32.768 connessioni concorrenti max multi_accept on; # Accetta tutte le connessioni in sospeso per ogni ciclo di eventi accept_mutex off; # Non necessario con epoll + reuseport}L’override di Systemd in /etc/systemd/system/nginx.service.d/override.conf imposta LimitNOFILE=65535 in modo corrispondente.
Buffer Proxy
Sezione intitolata “Buffer Proxy”proxy_buffering on;proxy_buffer_size 16k; # Buffer degli header (gestisce grandi header CDN)proxy_buffers 64 16k; # 1 MB per connessione (64 x 16k)proxy_busy_buffers_size 256k; # Può inviare 256k al client mentre legge ancoraLa dimensione del busy buffer di 256k è critica — deve essere superiore alla risposta più grande memorizzata nella cache (Juice Shop è 75 KB). L’impostazione originale a 64k causava serializzazione sotto carico.
Compressione Gzip
Sezione intitolata “Compressione Gzip”gzip on;gzip_comp_level 4; # Bilanciamento: ~85% della compressione massima a ~40% della CPUgzip_min_length 256; # Salta le risposte piccole (overhead dell'header gzip)gzip_vary on; # Vary: Accept-Encoding per una corretta memorizzazione in cachegzip_proxied any; # Comprime tutte le risposte proxygzip_types text/plain text/css text/javascript text/xml application/json application/javascript application/xml application/xml+rss application/atom+xml application/ld+json application/manifest+json image/svg+xml;Cache dei File Aperti
Sezione intitolata “Cache dei File Aperti”open_file_cache max=200000 inactive=20s;open_file_cache_valid 30s;open_file_cache_min_uses 2;open_file_cache_errors on;Memorizza nella cache i descrittori di file e i metadati per gli oggetti in cache, eliminando le syscall stat() e open() sui file più acceduti.
Keepalive del Client
Sezione intitolata “Keepalive del Client”keepalive_timeout 65;keepalive_requests 100000; # Era 1000 — causava il riciclo delle connessioni a 90K req/sA 90K req/s con keepalive_requests 1000, le connessioni venivano riciclate ogni 11 secondi, generando socket TIME_WAIT. L’aumento a 100.000 ha eliminato completamente questo problema.
Logging degli Accessi
Sezione intitolata “Logging degli Accessi”log_format cdn '$remote_addr [$time_local] "$request" $status $body_bytes_sent $upstream_cache_status $request_time';access_log /var/log/nginx/access.log cdn buffer=256k flush=5s;Il formato di log cdn include $upstream_cache_status (HIT/MISS) e $request_time per l’analisi della latenza. Il logging con buffer (256k/flush ogni 5s) riduce l’overhead di I/O sotto carico elevato.
Keepalive Upstream
Sezione intitolata “Keepalive Upstream”upstream origin_backend { server 20.12.78.159:80; keepalive 256; # Connessioni persistenti per worker verso l'origine keepalive_timeout 60s; keepalive_requests 1000;}Con 4 worker x 256 keepalive = 1.024 connessioni attive verso l’origine. Combinato con proxy_http_version 1.1 e proxy_set_header Connection "", elimina l’overhead dell’handshake TCP ad ogni cache miss.
Configurazione della Cache
Sezione intitolata “Configurazione della Cache”Percorso della Cache
Sezione intitolata “Percorso della Cache”proxy_cache_path /var/cache/nginx/cdn levels=1:2 keys_zone=cdn_cache:32m max_size=25g inactive=24h use_temp_path=off;| Parametro | Valore | Scopo |
|---|---|---|
keys_zone=cdn_cache:32m | 32 MB di memoria condivisa | Memorizza ~256.000 chiavi di cache e metadati |
max_size=25g | Limite disco di 25 GB | Utilizza la maggior parte del disco OS da 30 GB; eviction LRU al limite |
inactive=24h | Timeout di inattività di 24 ore | Il contenuto non acceduto per 24h viene rimosso (diverso dal TTL) |
use_temp_path=off | Scrittura diretta nella dir cache | Evita spostamenti di file tra filesystem diversi |
Comportamento della Cache
Sezione intitolata “Comportamento della Cache”proxy_cache cdn_cache;proxy_cache_valid 200 301 302 4h;proxy_cache_valid 404 1m;proxy_cache_key "$scheme$host$request_uri";proxy_cache_lock on;proxy_cache_lock_age 3s;proxy_cache_lock_timeout 3s;proxy_cache_background_update on;proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;proxy_ignore_headers Set-Cookie Cache-Control Expires Vary;
proxy_hide_header X-Cache-Status;proxy_hide_header Vary;| Direttiva | Valore | Scopo |
|---|---|---|
proxy_cache_valid 200 301 302 4h | TTL di 4 ore | Contenuto in cache valido per 4 ore (aumentato per ridurre i cali di throughput durante le ondate di aggiornamento) |
proxy_cache_lock on | Prevenzione thundering herd | Solo 1 richiesta raggiunge l’origine per URL non in cache; le altre attendono il riempimento della cache |
proxy_cache_lock_age 3s | Timeout del lock | Se la prima richiesta non è completata entro 3s, ne viene inoltrata un’altra |
proxy_cache_background_update on | Aggiornamento a latenza zero | Serve il contenuto obsoleto immediatamente mentre aggiorna in background |
proxy_cache_use_stale | Resilienza | Serve contenuto obsoleto durante errori dell’origine (500/502/503/504) o durante l’aggiornamento |
proxy_ignore_headers | Forza la memorizzazione in cache | Ignora Set-Cookie, Cache-Control, Expires e Vary dell’origine — è il CDN a decidere TTL e comportamento Vary (Juice Shop invia max-age=0 e tripli header Vary che impedivano un’efficace memorizzazione in cache) |
proxy_hide_header X-Cache-Status | Rimuove l’header dell’origine | L’NGINX dell’origine aggiunge il proprio X-Cache-Status — viene rimosso affinché sia visibile solo lo stato di cache del CDN |
proxy_hide_header Vary | Previene la frammentazione della cache | L’origine invia più header Vary: Accept-Encoding. La loro rimozione previene la frammentazione della chiave di cache tra le varie permutazioni di Accept-Encoding. gzip_vary on di NGINX aggiunge automaticamente il corretto singolo header Vary |
Timeout Proxy
Sezione intitolata “Timeout Proxy”proxy_read_timeout 30s;proxy_connect_timeout 10s;proxy_send_timeout 15s;Concede all’origine più tempo di risposta sotto carico mantenendo un rapido fallimento in caso di problemi di connessione.
Blocco Server
Sezione intitolata “Blocco Server”server { listen 80 reuseport; # Il kernel distribuisce le connessioni tra tutti i 4 worker server_name _;}reuseport abilita SO_REUSEPORT — il kernel distribuisce le connessioni in ingresso direttamente ai processi worker, eliminando la contesa sull’accept mutex.
Header dei Vendor CDN
Sezione intitolata “Header dei Vendor CDN”Il simulatore inietta header da tutti e cinque i principali vendor CDN contemporaneamente. Questo consente di configurare F5 XC con l‘“Header IP Client Attendibile” di qualsiasi vendor e di vedere payload di header realistici indipendentemente dal CDN simulato.
Header Standard di Settore (Tutti i CDN)
Sezione intitolata “Header Standard di Settore (Tutti i CDN)”| Header | Valore | Scopo |
|---|---|---|
X-Forwarded-For | Catena IP client | IP inoltrato standard |
X-Forwarded-Proto | http o https | Protocollo originale del client |
X-Forwarded-Host | Nome host originale | Header Host originale |
X-Forwarded-Port | Porta del server | Porta originale |
X-Real-IP | IP del client | IP singolo del client (convenzione nginx) |
Via | 1.1 cdn-simulator | Identificazione del proxy |
Forwarded | Formato RFC 7239 | Header di inoltro standardizzato |
CDN-Loop | cdn-simulator | Rilevamento dei loop |
Header Akamai
Sezione intitolata “Header Akamai”| Header | Valore | Scopo |
|---|---|---|
True-Client-IP | IP del client | Indirizzo IP originale dell’utente finale |
X-Akamai-Edgescape | Stringa geo composta | georegion, country_code, region_code, city, dma, pmsa, msa, areacode, county, fips, lat, long, timezone, zip, continent, throughput, bw, network, asnum, network_type |
X-Akamai-Device-Characteristics | Proprietà del dispositivo | brand_name, model_name, is_mobile, is_tablet, is_wireless_device, device_os, device_os_version, resolution_width, resolution_height |
X-Akamai-Request-ID | UUID della richiesta | Identificatore univoco della richiesta |
Header Cloudflare
Sezione intitolata “Header Cloudflare”| Header | Valore | Scopo |
|---|---|---|
CF-Connecting-IP | IP del client | IP reale del client (sempre presente) |
CF-IPCountry | US | Codice paese a due lettere |
cf-ipcity | San Jose | Città del client |
cf-ipcontinent | NA | Codice continente |
cf-iplatitude / cf-iplongitude | Coordinate | Geolocalizzazione |
cf-region / cf-region-code | California / CA | Informazioni sulla regione |
cf-metro-code | 807 | Codice area metropolitana US |
cf-postal-code | 95113 | Codice postale |
cf-timezone | America/Los_Angeles | Fuso orario IANA |
Cf-Ray | {request_id}-SJC | ID ray univoco con codice IATA del POP |
CF-Visitor | {"scheme":"https"} | Informazioni sul protocollo del visitatore |
cf-bot-score | 85 | Punteggio bot (1=bot, 99=umano) |
cf-verified-bot | false | Flag bot legittimo noto |
cf-ja3-hash | e7d705a3286e19ea42f587b344ee6865 | Fingerprint TLS JA3 |
cf-ja4 | t13d1516h2_8daaf6152771_b0da82dd1658 | Fingerprint TLS JA4 |
Header Amazon CloudFront
Sezione intitolata “Header Amazon CloudFront”| Header | Valore | Scopo |
|---|---|---|
CloudFront-Viewer-Address | IP:porta | IP del client e porta sorgente |
CloudFront-Viewer-Country | US | Codice paese |
CloudFront-Viewer-Country-Name | United States | Nome completo del paese |
CloudFront-Viewer-Country-Region | CA | Codice regione |
CloudFront-Viewer-Country-Region-Name | California | Nome completo della regione |
CloudFront-Viewer-City | San Jose | Città del client |
CloudFront-Viewer-Postal-Code | 95113 | Codice postale |
CloudFront-Viewer-Latitude / Longitude | 37.33530 / -121.89300 | Geolocalizzazione |
CloudFront-Viewer-Time-Zone | America/Los_Angeles | Fuso orario IANA |
CloudFront-Viewer-Metro-Code | 807 | Codice area metropolitana US |
CloudFront-Viewer-ASN | 7018 | Numero di Sistema Autonomo |
CloudFront-Viewer-Http-Version | 2.0 | Versione HTTP del client |
CloudFront-Forwarded-Proto | https | Protocollo originale |
CloudFront-Viewer-TLS | TLSv1.3:TLS_AES_128_GCM_SHA256:sessionResumed | Dettagli TLS |
CloudFront-Viewer-JA3-Fingerprint | e7d705a3286e19ea42f587b344ee6865 | Fingerprint TLS JA3 |
CloudFront-Is-Desktop-Viewer | true/false | Rilevamento dispositivo |
CloudFront-Is-Mobile-Viewer | true/false | Rilevamento dispositivo |
CloudFront-Is-Tablet-Viewer | true/false | Rilevamento dispositivo |
CloudFront-Is-SmartTV-Viewer | false | Rilevamento dispositivo |
X-Amz-Cf-Id | ID codificato | Identificatore richiesta CloudFront |
Header Fastly
Sezione intitolata “Header Fastly”| Header | Valore | Scopo |
|---|---|---|
Fastly-Client-IP | IP del client | IP reale del client |
Fastly-SSL | 1 | La connessione era su TLS |
Fastly-Client | 1 | Richiesta lato client (non shield) |
Fastly-FF | cache-sjc3120-SJC | Identificazione del nodo cache |
X-Geo-Country-Code | US | Paese (convenzione variabile VCL) |
X-Geo-Country-Code3 | USA | Codice paese a tre lettere |
X-Geo-Country-Name | United States | Nome completo del paese |
X-Geo-City | San Jose | Città del client |
X-Geo-Region | CA | Codice regione |
X-Geo-Continent-Code | NA | Continente |
X-Geo-Latitude / X-Geo-Longitude | 37.3353 / -121.8938 | Geolocalizzazione |
X-Geo-Postal-Code | 95113 | Codice postale |
X-Geo-Metro-Code | 807 | Codice area metropolitana US |
X-Geo-ASN | 7018 | Numero di Sistema Autonomo |
X-Geo-Conn-Speed | broadband | Classe di velocità della connessione |
X-Geo-Conn-Type | wired | Tipo di connessione |
Header Azure Front Door
Sezione intitolata “Header Azure Front Door”| Header | Valore | Scopo |
|---|---|---|
X-Azure-ClientIP | IP del client | Indirizzo IP del client |
X-Azure-SocketIP | IP del client | IP sorgente del socket TCP |
X-Azure-Ref | Stringa di riferimento codificata | Riferimento univoco della richiesta per la risoluzione dei problemi |
X-Azure-FDID | a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1 | Identificatore della risorsa Front Door |
X-Azure-RequestChain | hops=1 | Conteggio hop per rilevamento loop |
Header di Risposta (Aggiunti alle Risposte al Client)
Sezione intitolata “Header di Risposta (Aggiunti alle Risposte al Client)”| Header | Valori | Scopo |
|---|---|---|
X-Cache-Status | HIT, MISS, EXPIRED, STALE, UPDATING | Comportamento della cache per questa richiesta |
X-CDN-Edge | cdn-simulator | Identifica questo nodo edge |
X-CDN-POP | SJC | Codice IATA del Point of Presence simulato |
X-Served-By | cache-sjc3120-SJC | Nodo cache simulato in formato Fastly |
X-Request-ID | UUID (per richiesta) | Identificatore univoco della richiesta |
Rilevamento Dispositivi
Sezione intitolata “Rilevamento Dispositivi”Il simulatore rileva il tipo di dispositivo dall’header User-Agent utilizzando le direttive map di NGINX:
- Mobile: Corrisponde a iPhone, Android (non tablet), iPod, BlackBerry, Opera Mini, IEMobile
- Tablet: Corrisponde a iPad, tablet Android, Kindle, PlayBook
- Desktop: Default quando non corrisponde né mobile né tablet
Il tipo di dispositivo si riflette in:
CloudFront-Is-Desktop-Viewer/CloudFront-Is-Mobile-Viewer/CloudFront-Is-Tablet-ViewerX-Akamai-Device-Characteristics(campiis_mobile,is_tablet,is_wireless_device)
Operazioni
Sezione intitolata “Operazioni”Modifica del Server di Origine
Sezione intitolata “Modifica del Server di Origine”ssh azureuser@<PUBLIC_IP>
# Aggiorna il server upstreamsudo sed -i 's|server .*;|server NEW_HOST:80;|' /etc/nginx/conf.d/cdn-edge.conf
# Svuota la cache e ricaricasudo rm -rf /var/cache/nginx/cdn/*sudo nginx -t && sudo systemctl reload nginxIn alternativa, aggiorna origin_host in terraform.tfvars ed esegui terraform apply per riprovisionare.
Svuotamento della Cache
Sezione intitolata “Svuotamento della Cache”ssh azureuser@<PUBLIC_IP>sudo rm -rf /var/cache/nginx/cdn/*sudo systemctl reload nginxVerifica delle Statistiche di Cache
Sezione intitolata “Verifica delle Statistiche di Cache”# Conteggio oggetti e utilizzo discosudo find /var/cache/nginx/cdn -type f | wc -lsudo du -sh /var/cache/nginx/cdn
# Log degli accessi recenti con stato della cachetail -20 /var/log/nginx/access.logMonitoraggio Sotto Carico
Sezione intitolata “Monitoraggio Sotto Carico”# Connessioni in tempo reale e stati dei socketss -s
# Utilizzo CPU dei worker NGINXtop -bn1 | grep nginx
# Connessioni keepalive upstreamss -tn state established dst <ORIGIN_IP> | wc -l
# Conteggio socket TIME_WAITss -tn state time-wait | wc -lRisultati del Benchmark delle Prestazioni
Sezione intitolata “Risultati del Benchmark delle Prestazioni”Verificati in un test di carico continuo di 48 ore:
| Metrica | Valore |
|---|---|
| Throughput di picco (in cache) | 172.540 req/s |
| Throughput sostenuto (in cache) | 85.000-103.000 req/s |
| Connessioni di picco | 15.000 concorrenti |
| Rapporto di cache hit | 100% (a cache riscaldata) |
| Memoria sotto carico | 1,2 GB stabile (8% di 16 GB) |
| CPU al picco | 100% (4 core - la CPU è il limite) |
| Errori durante il test di 48h | 0 |
| Memory leak | Nessuno rilevato |
| Connection leak | Nessuno rilevato |