- Accueil
- Simulateur CDN
- Configuration NGINX
Configuration NGINX
Le provisionnement cloud-init déploie une configuration NGINX d’edge CDN entièrement optimisée pour les performances. Cette page documente chaque couche de configuration, du réglage du noyau au comportement du cache jusqu’à l’injection des en-têtes fournisseurs. Tous les paramètres ont été vérifiés lors d’un test de charge continu de 48 heures atteignant un pic de 172 540 req/s.
Fichiers de configuration
Section intitulée « Fichiers de configuration »| Fichier | Objectif |
|---|---|
/etc/sysctl.d/99-cdn-tuning.conf | Réglage réseau du noyau Linux |
/etc/systemd/system/nginx.service.d/override.conf | Limites des descripteurs de fichiers pour NGINX |
/etc/security/limits.d/99-nginx.conf | Limites au niveau du système d’exploitation pour l’utilisateur www-data |
/etc/nginx/nginx.conf | Configuration principale NGINX (workers, tampons, gzip, journalisation) |
/etc/nginx/conf.d/cdn-edge.conf | Configuration proxy CDN (cache, amont, en-têtes) |
Réglage du noyau
Section intitulée « Réglage du noyau »Appliqué via /etc/sysctl.d/99-cdn-tuning.conf au démarrage.
| Paramètre | Valeur | Défaut | Objectif |
|---|---|---|---|
net.core.somaxconn | 65535 | 4096 | Taille de la file d’attente du backlog d’écoute |
net.core.netdev_max_backlog | 65535 | 1000 | Backlog de paquets entrants par CPU |
net.ipv4.tcp_max_syn_backlog | 65535 | 256 | File d’attente des requêtes SYN (évite les pertes en cas de burst) |
net.ipv4.tcp_tw_reuse | 1 | 2 | Réutilisation des sockets TIME_WAIT pour les connexions sortantes |
net.ipv4.ip_local_port_range | 1024-65535 | 32768-60999 | Plage de ports éphémères (64 K contre 28 K) |
net.core.rmem_max | 16 Mo | 212 Ko | Tampon de réception maximum du socket |
net.core.wmem_max | 16 Mo | 212 Ko | Tampon d’envoi maximum du socket |
net.ipv4.tcp_rmem | 4K/87K/16M | 4K/131K/6M | Tampon de réception par socket (min/défaut/max) |
net.ipv4.tcp_wmem | 4K/65K/16M | 4K/16K/4M | Tampon d’envoi par socket (min/défaut/max) |
net.ipv4.tcp_fin_timeout | 15 | 60 | Délai d’expiration FIN_WAIT_2 (libération plus rapide des sockets) |
net.ipv4.tcp_keepalive_time | 300 | 7200 | Démarrage des sondes keepalive après 5 min d’inactivité |
net.ipv4.tcp_slow_start_after_idle | 0 | 1 | Maintien de la fenêtre de congestion active sur les connexions inactives |
net.ipv4.tcp_max_tw_buckets | 2000000 | ~65536 | Nombre maximum de sockets TIME_WAIT |
fs.file-max | 2097152 | variable | Limite système des descripteurs de fichiers |
vm.swappiness | 10 | 60 | Préférer la RAM au swap pour les données du cache |
Configuration principale NGINX
Section intitulée « Configuration principale NGINX »Workers et connexions
Section intitulée « Workers et connexions »worker_processes auto; # 4 workers sur D4s_v5 (1 par vCPU)worker_rlimit_nofile 65535; # Limite des descripteurs de fichiers par worker
events { use epoll; # Modèle d'événements optimisé pour Linux worker_connections 8192; # 4 workers x 8192 = 32 768 connexions simultanées max multi_accept on; # Accepter toutes les connexions en attente par boucle d'événements accept_mutex off; # Non nécessaire avec epoll + reuseport}La surcharge systemd dans /etc/systemd/system/nginx.service.d/override.conf définit LimitNOFILE=65535 pour correspondre.
Tampons proxy
Section intitulée « Tampons proxy »proxy_buffering on;proxy_buffer_size 16k; # Tampon d'en-têtes (gère les grands en-têtes CDN)proxy_buffers 64 16k; # 1 Mo par connexion (64 x 16k)proxy_busy_buffers_size 256k; # Peut envoyer 256k au client tout en continuant la lectureLa taille du tampon busy à 256k est critique — elle doit dépasser la plus grande réponse mise en cache (Juice Shop fait 75 Ko). Le paramètre initial de 64k causait une sérialisation sous charge.
Compression Gzip
Section intitulée « Compression Gzip »gzip on;gzip_comp_level 4; # Équilibre : ~85% de la compression maximale à ~40% du CPUgzip_min_length 256; # Ignorer les petites réponses (surcharge d'en-tête gzip)gzip_vary on; # Vary: Accept-Encoding pour un cache correctgzip_proxied any; # Compresser toutes les réponses proxifiéesgzip_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 des fichiers ouverts
Section intitulée « Cache des fichiers ouverts »open_file_cache max=200000 inactive=20s;open_file_cache_valid 30s;open_file_cache_min_uses 2;open_file_cache_errors on;Met en cache les descripteurs de fichiers et les métadonnées des objets mis en cache, éliminant les appels système stat() et open() sur les fichiers fréquemment accédés.
Keepalive client
Section intitulée « Keepalive client »keepalive_timeout 65;keepalive_requests 100000; # Était 1000 — causait un recyclage des connexions à 90 000 req/sÀ 90 000 req/s avec keepalive_requests 1000, les connexions étaient recyclées toutes les 11 secondes, générant des sockets TIME_WAIT. L’augmentation à 100 000 a entièrement éliminé ce problème.
Journalisation des accès
Section intitulée « Journalisation des accès »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;Le format de journal cdn inclut $upstream_cache_status (HIT/MISS) et $request_time pour l’analyse de la latence. La journalisation en tampon (256k/flush toutes les 5s) réduit la surcharge d’E/S sous forte charge.
Connexions persistantes en amont
Section intitulée « Connexions persistantes en amont »upstream origin_backend { server 20.12.78.159:80; keepalive 256; # Connexions persistantes par worker vers l'origine keepalive_timeout 60s; keepalive_requests 1000;}Avec 4 workers x 256 keepalive = 1 024 connexions actives vers l’origine. Combiné avec proxy_http_version 1.1 et proxy_set_header Connection "", cela élimine la surcharge de la poignée de main TCP à chaque défaut de cache.
Configuration du cache
Section intitulée « Configuration du cache »Chemin du cache
Section intitulée « Chemin du 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;| Paramètre | Valeur | Objectif |
|---|---|---|
keys_zone=cdn_cache:32m | 32 Mo de mémoire partagée | Stocke ~256 000 clés de cache et métadonnées |
max_size=25g | Limite disque de 25 Go | Utilise la majeure partie du disque OS de 30 Go ; éviction LRU à la limite |
inactive=24h | Délai d’inactivité de 24 heures | Le contenu non consulté pendant 24h est évincé (différent du TTL) |
use_temp_path=off | Écriture directe dans le répertoire du cache | Évite les déplacements de fichiers entre systèmes de fichiers |
Comportement du cache
Section intitulée « Comportement du 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;| Directive | Valeur | Objectif |
|---|---|---|
proxy_cache_valid 200 301 302 4h | TTL de 4 heures | Contenu mis en cache valide pendant 4 heures (augmenté pour réduire les baisses de débit lors des vagues de rafraîchissement) |
proxy_cache_lock on | Prévention du thundering herd | Une seule requête est envoyée à l’origine par URL non mise en cache ; les autres attendent le remplissage du cache |
proxy_cache_lock_age 3s | Délai d’expiration du verrou | Si la première requête n’est pas terminée en 3s, une autre est autorisée à passer |
proxy_cache_background_update on | Rafraîchissement sans latence | Sert immédiatement le contenu périmé pendant le rafraîchissement en arrière-plan |
proxy_cache_use_stale | Résilience | Sert le contenu périmé lors d’erreurs d’origine (500/502/503/504) ou pendant la mise à jour |
proxy_ignore_headers | Forcer la mise en cache | Ignore les en-têtes Set-Cookie, Cache-Control, Expires, Vary de l’origine — le CDN décide du TTL et du comportement Vary (Juice Shop envoie max-age=0 et trois en-têtes Vary qui empêchaient une mise en cache efficace) |
proxy_hide_header X-Cache-Status | Supprimer l’en-tête d’origine | NGINX d’origine ajoute son propre X-Cache-Status — le supprimer afin que seul le statut de cache du CDN soit visible |
proxy_hide_header Vary | Prévenir la fragmentation du cache | L’origine envoie plusieurs en-têtes Vary: Accept-Encoding. Les supprimer évite la fragmentation des clés de cache selon les permutations d’Accept-Encoding. Le paramètre gzip_vary on de NGINX ajoute automatiquement le bon en-tête Vary unique |
Délais d’expiration du proxy
Section intitulée « Délais d’expiration du proxy »proxy_read_timeout 30s;proxy_connect_timeout 10s;proxy_send_timeout 15s;Accorde plus de temps de réponse à l’origine sous charge tout en échouant rapidement en cas de problèmes de connexion.
Bloc serveur
Section intitulée « Bloc serveur »server { listen 80 reuseport; # Le noyau distribue les connexions sur les 4 workers server_name _;}reuseport active SO_REUSEPORT — le noyau distribue directement les connexions entrantes aux processus workers, éliminant la contention du mutex d’acceptation.
En-têtes des fournisseurs CDN
Section intitulée « En-têtes des fournisseurs CDN »Le simulateur injecte simultanément des en-têtes des cinq principaux fournisseurs CDN. Cela permet de configurer F5 XC avec l’en-tête « Trusted Client IP Header » de n’importe quel fournisseur et de voir des charges d’en-têtes réalistes, quel que soit le CDN simulé.
En-têtes standard du secteur (tous les CDN)
Section intitulée « En-têtes standard du secteur (tous les CDN) »| En-tête | Valeur | Objectif |
|---|---|---|
X-Forwarded-For | Chaîne IP client | IP de transfert standard |
X-Forwarded-Proto | http ou https | Protocole client d’origine |
X-Forwarded-Host | Nom d’hôte d’origine | En-tête Host d’origine |
X-Forwarded-Port | Port serveur | Port d’origine |
X-Real-IP | IP client | IP client unique (convention nginx) |
Via | 1.1 cdn-simulator | Identification du proxy |
Forwarded | Format RFC 7239 | En-tête de transfert standardisé |
CDN-Loop | cdn-simulator | Détection de boucle |
En-têtes Akamai
Section intitulée « En-têtes Akamai »| En-tête | Valeur | Objectif |
|---|---|---|
True-Client-IP | IP client | Adresse IP de l’utilisateur final d’origine |
X-Akamai-Edgescape | Chaîne géographique composée | 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 | Propriétés de l’appareil | 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 de la requête | Identifiant unique de la requête |
En-têtes Cloudflare
Section intitulée « En-têtes Cloudflare »| En-tête | Valeur | Objectif |
|---|---|---|
CF-Connecting-IP | IP client | Véritable IP client (toujours présente) |
CF-IPCountry | US | Code pays à deux lettres |
cf-ipcity | San Jose | Ville du client |
cf-ipcontinent | NA | Code continent |
cf-iplatitude / cf-iplongitude | Coordonnées | Géolocalisation |
cf-region / cf-region-code | California / CA | Informations de région |
cf-metro-code | 807 | Code de zone métropolitaine US |
cf-postal-code | 95113 | Code postal |
cf-timezone | America/Los_Angeles | Fuseau horaire IANA |
Cf-Ray | {request_id}-SJC | Identifiant ray unique avec code IATA du POP |
CF-Visitor | {"scheme":"https"} | Informations sur le protocole du visiteur |
cf-bot-score | 85 | Score bot (1=bot, 99=humain) |
cf-verified-bot | false | Indicateur de bot reconnu comme valide |
cf-ja3-hash | e7d705a3286e19ea42f587b344ee6865 | Empreinte TLS JA3 |
cf-ja4 | t13d1516h2_8daaf6152771_b0da82dd1658 | Empreinte TLS JA4 |
En-têtes Amazon CloudFront
Section intitulée « En-têtes Amazon CloudFront »| En-tête | Valeur | Objectif |
|---|---|---|
CloudFront-Viewer-Address | IP:port | IP client et port source |
CloudFront-Viewer-Country | US | Code pays |
CloudFront-Viewer-Country-Name | United States | Nom complet du pays |
CloudFront-Viewer-Country-Region | CA | Code de région |
CloudFront-Viewer-Country-Region-Name | California | Nom complet de la région |
CloudFront-Viewer-City | San Jose | Ville du client |
CloudFront-Viewer-Postal-Code | 95113 | Code postal |
CloudFront-Viewer-Latitude / Longitude | 37.33530 / -121.89300 | Géolocalisation |
CloudFront-Viewer-Time-Zone | America/Los_Angeles | Fuseau horaire IANA |
CloudFront-Viewer-Metro-Code | 807 | Code de zone métropolitaine US |
CloudFront-Viewer-ASN | 7018 | Numéro de système autonome |
CloudFront-Viewer-Http-Version | 2.0 | Version HTTP du client |
CloudFront-Forwarded-Proto | https | Protocole d’origine |
CloudFront-Viewer-TLS | TLSv1.3:TLS_AES_128_GCM_SHA256:sessionResumed | Détails TLS |
CloudFront-Viewer-JA3-Fingerprint | e7d705a3286e19ea42f587b344ee6865 | Empreinte TLS JA3 |
CloudFront-Is-Desktop-Viewer | true/false | Détection d’appareil |
CloudFront-Is-Mobile-Viewer | true/false | Détection d’appareil |
CloudFront-Is-Tablet-Viewer | true/false | Détection d’appareil |
CloudFront-Is-SmartTV-Viewer | false | Détection d’appareil |
X-Amz-Cf-Id | ID encodé | Identifiant de requête CloudFront |
En-têtes Fastly
Section intitulée « En-têtes Fastly »| En-tête | Valeur | Objectif |
|---|---|---|
Fastly-Client-IP | IP client | Véritable IP client |
Fastly-SSL | 1 | La connexion était sur TLS |
Fastly-Client | 1 | Requête côté client (pas shield) |
Fastly-FF | cache-sjc3120-SJC | Identification du nœud de cache |
X-Geo-Country-Code | US | Pays (convention de variable VCL) |
X-Geo-Country-Code3 | USA | Code pays à trois lettres |
X-Geo-Country-Name | United States | Nom complet du pays |
X-Geo-City | San Jose | Ville du client |
X-Geo-Region | CA | Code de région |
X-Geo-Continent-Code | NA | Continent |
X-Geo-Latitude / X-Geo-Longitude | 37.3353 / -121.8938 | Géolocalisation |
X-Geo-Postal-Code | 95113 | Code postal |
X-Geo-Metro-Code | 807 | Code de zone métropolitaine US |
X-Geo-ASN | 7018 | Numéro de système autonome |
X-Geo-Conn-Speed | broadband | Classe de vitesse de connexion |
X-Geo-Conn-Type | wired | Type de connexion |
En-têtes Azure Front Door
Section intitulée « En-têtes Azure Front Door »| En-tête | Valeur | Objectif |
|---|---|---|
X-Azure-ClientIP | IP client | Adresse IP du client |
X-Azure-SocketIP | IP client | IP source du socket TCP |
X-Azure-Ref | Chaîne de référence encodée | Référence unique de requête pour le dépannage |
X-Azure-FDID | a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1 | Identifiant de ressource Front Door |
X-Azure-RequestChain | hops=1 | Compteur de sauts pour la détection de boucle |
En-têtes de réponse (ajoutés aux réponses client)
Section intitulée « En-têtes de réponse (ajoutés aux réponses client) »| En-tête | Valeurs | Objectif |
|---|---|---|
X-Cache-Status | HIT, MISS, EXPIRED, STALE, UPDATING | Comportement du cache pour cette requête |
X-CDN-Edge | cdn-simulator | Identifie ce nœud edge |
X-CDN-POP | SJC | Code IATA du point de présence simulé |
X-Served-By | cache-sjc3120-SJC | Nœud de cache simulé au format Fastly |
X-Request-ID | UUID (par requête) | Identifiant unique de la requête |
Détection des appareils
Section intitulée « Détection des appareils »Le simulateur détecte le type d’appareil depuis l’en-tête User-Agent à l’aide de directives map NGINX :
- Mobile : Correspond à iPhone, Android (hors tablette), iPod, BlackBerry, Opera Mini, IEMobile
- Tablette : Correspond à iPad, tablette Android, Kindle, PlayBook
- Bureau : Valeur par défaut lorsque ni mobile ni tablette ne correspond
Le type d’appareil est reflété dans :
CloudFront-Is-Desktop-Viewer/CloudFront-Is-Mobile-Viewer/CloudFront-Is-Tablet-ViewerX-Akamai-Device-Characteristics(champsis_mobile,is_tablet,is_wireless_device)
Opérations
Section intitulée « Opérations »Modifier le serveur d’origine
Section intitulée « Modifier le serveur d’origine »ssh azureuser@<PUBLIC_IP>
# Mettre à jour le serveur amontsudo sed -i 's|server .*;|server NEW_HOST:80;|' /etc/nginx/conf.d/cdn-edge.conf
# Vider le cache et rechargersudo rm -rf /var/cache/nginx/cdn/*sudo nginx -t && sudo systemctl reload nginxOu mettez à jour origin_host dans terraform.tfvars et exécutez terraform apply pour re-provisionner.
Vider le cache
Section intitulée « Vider le cache »ssh azureuser@<PUBLIC_IP>sudo rm -rf /var/cache/nginx/cdn/*sudo systemctl reload nginxVérifier les statistiques du cache
Section intitulée « Vérifier les statistiques du cache »# Nombre d'objets et utilisation du disquesudo find /var/cache/nginx/cdn -type f | wc -lsudo du -sh /var/cache/nginx/cdn
# Journal d'accès récent avec statut du cachetail -20 /var/log/nginx/access.logSurveillance sous charge
Section intitulée « Surveillance sous charge »# Connexions en temps réel et états des socketsss -s
# Utilisation CPU des workers NGINXtop -bn1 | grep nginx
# Connexions keepalive en amontss -tn state established dst <ORIGIN_IP> | wc -l
# Nombre de sockets TIME_WAITss -tn state time-wait | wc -lRésultats du benchmark de performance
Section intitulée « Résultats du benchmark de performance »Vérifié lors d’un test de charge continu de 48 heures :
| Métrique | Valeur |
|---|---|
| Débit de pointe (mis en cache) | 172 540 req/s |
| Débit soutenu (mis en cache) | 85 000-103 000 req/s |
| Connexions de pointe | 15 000 simultanées |
| Taux de succès du cache | 100% (une fois réchauffé) |
| Mémoire sous charge | 1,2 Go stable (8% des 16 Go) |
| CPU au pic | 100% (4 cœurs - le CPU est le plafond) |
| Erreurs durant le test de 48h | 0 |
| Fuites mémoire | Aucune détectée |
| Fuites de connexions | Aucune détectée |