Pular para o conteúdo

Configuração do NGINX

O provisionamento via cloud-init implanta uma configuração de borda CDN do NGINX totalmente otimizada para desempenho. Esta página documenta cada camada de configuração, desde o ajuste do kernel até o comportamento do cache e a injeção de cabeçalhos de fornecedores. Todas as configurações foram verificadas em um teste de carga contínuo de 48 horas com pico de 172.540 req/s.

ArquivoFinalidade
/etc/sysctl.d/99-cdn-tuning.confAjuste de rede do kernel Linux
/etc/systemd/system/nginx.service.d/override.confLimites de descritores de arquivo para o NGINX
/etc/security/limits.d/99-nginx.confLimites no nível do SO para o usuário www-data
/etc/nginx/nginx.confConfiguração principal do NGINX (workers, buffers, gzip, logging)
/etc/nginx/conf.d/cdn-edge.confConfiguração de proxy CDN (cache, upstream, cabeçalhos)

Aplicado via /etc/sysctl.d/99-cdn-tuning.conf na inicialização.

ParâmetroValorPadrãoFinalidade
net.core.somaxconn655354096Tamanho da fila de backlog de escuta
net.core.netdev_max_backlog655351000Backlog de pacotes de entrada por CPU
net.ipv4.tcp_max_syn_backlog65535256Fila de requisições SYN (evita descartes em rajadas)
net.ipv4.tcp_tw_reuse12Reutilizar sockets TIME_WAIT para conexões de saída
net.ipv4.ip_local_port_range1024-6553532768-60999Intervalo de portas efêmeras (64K vs 28K)
net.core.rmem_max16 MB212 KBBuffer máximo de recepção do socket
net.core.wmem_max16 MB212 KBBuffer máximo de envio do socket
net.ipv4.tcp_rmem4K/87K/16M4K/131K/6MBuffer de recepção por socket (mín/padrão/máx)
net.ipv4.tcp_wmem4K/65K/16M4K/16K/4MBuffer de envio por socket (mín/padrão/máx)
net.ipv4.tcp_fin_timeout1560Timeout FIN_WAIT_2 (limpeza mais rápida de sockets)
net.ipv4.tcp_keepalive_time3007200Iniciar probes de keepalive após 5 min de ociosidade
net.ipv4.tcp_slow_start_after_idle01Manter a janela de congestionamento aquecida em conexões ociosas
net.ipv4.tcp_max_tw_buckets2000000~65536Máximo de sockets TIME_WAIT
fs.file-max2097152variaLimite de descritores de arquivo em todo o sistema
vm.swappiness1060Preferir RAM ao swap para dados em cache
worker_processes auto; # 4 workers no D4s_v5 (1 por vCPU)
worker_rlimit_nofile 65535; # Limite de descritores de arquivo por worker
events {
use epoll; # Modelo de eventos otimizado para Linux
worker_connections 8192; # 4 workers x 8192 = 32.768 máximo simultâneo
multi_accept on; # Aceita todas as conexões pendentes por loop de eventos
accept_mutex off; # Desnecessário com epoll + reuseport
}

O override do Systemd em /etc/systemd/system/nginx.service.d/override.conf define LimitNOFILE=65535 para correspondência.

proxy_buffering on;
proxy_buffer_size 16k; # Buffer de cabeçalho (suporta grandes cabeçalhos CDN)
proxy_buffers 64 16k; # 1 MB por conexão (64 x 16k)
proxy_busy_buffers_size 256k; # Pode enviar 256k ao cliente enquanto ainda lê

O tamanho do busy buffer de 256k é crítico — deve exceder a maior resposta em cache (Juice Shop tem 75 KB). A configuração original de 64k causava serialização sob carga.

gzip on;
gzip_comp_level 4; # Equilíbrio: ~85% da compressão máxima com ~40% de CPU
gzip_min_length 256; # Ignora respostas pequenas (overhead do cabeçalho gzip)
gzip_vary on; # Vary: Accept-Encoding para caching correto
gzip_proxied any; # Comprime todas as respostas proxiadas
gzip_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;
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

Armazena em cache descritores de arquivo e metadados de objetos em cache, eliminando syscalls stat() e open() em arquivos acessados frequentemente.

keepalive_timeout 65;
keepalive_requests 100000; # Era 1000 — causava reciclagem de conexões a 90K req/s

A 90K req/s com keepalive_requests 1000, as conexões eram recicladas a cada 11 segundos, gerando sockets TIME_WAIT. Aumentar para 100.000 eliminou esse problema completamente.

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;

O formato de log cdn inclui $upstream_cache_status (HIT/MISS) e $request_time para análise de latência. O logging com buffer (256k/flush a cada 5s) reduz o overhead de E/S sob alta carga.

upstream origin_backend {
server 20.12.78.159:80;
keepalive 256; # Conexões persistentes por worker ao origin
keepalive_timeout 60s;
keepalive_requests 1000;
}

Com 4 workers x 256 keepalive = 1.024 conexões aquecidas ao origin. Combinado com proxy_http_version 1.1 e proxy_set_header Connection "", isso elimina o overhead do handshake TCP em cada cache miss.

proxy_cache_path /var/cache/nginx/cdn
levels=1:2
keys_zone=cdn_cache:32m
max_size=25g
inactive=24h
use_temp_path=off;
ParâmetroValorFinalidade
keys_zone=cdn_cache:32m32 MB de memória compartilhadaArmazena ~256.000 chaves de cache e metadados
max_size=25gLimite de disco de 25 GBUtiliza a maior parte do disco de 30 GB do SO; evição LRU ao atingir o limite
inactive=24hTimeout de inatividade de 24 horasConteúdo não acessado por 24h é evicado (diferente do TTL)
use_temp_path=offGrava diretamente no diretório de cacheEvita movimentação de arquivos entre sistemas de arquivos
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;
DiretivaValorFinalidade
proxy_cache_valid 200 301 302 4hTTL de 4 horasConteúdo em cache válido por 4 horas (aumentado para reduzir quedas de throughput durante onda de atualização)
proxy_cache_lock onPrevenção de thundering herdApenas 1 requisição vai ao origin por URL não cacheada; as demais aguardam o preenchimento do cache
proxy_cache_lock_age 3sTimeout de lockSe a primeira requisição não foi concluída em 3s, permite outra passar
proxy_cache_background_update onAtualização sem latênciaServe conteúdo stale imediatamente enquanto atualiza em segundo plano
proxy_cache_use_staleResiliênciaServe conteúdo stale durante erros do origin (500/502/503/504) ou durante atualização
proxy_ignore_headersForçar cachingIgnora Set-Cookie, Cache-Control, Expires e Vary do origin — o CDN decide TTL e comportamento de Vary (Juice Shop envia max-age=0 e três cabeçalhos Vary que impediam o caching efetivo)
proxy_hide_header X-Cache-StatusRemover cabeçalho do originO NGINX do origin adiciona seu próprio X-Cache-Status — remove-o para que apenas o status de cache do CDN fique visível
proxy_hide_header VaryEvitar fragmentação do cacheO origin envia múltiplos cabeçalhos Vary: Accept-Encoding. Removê-los evita a fragmentação da chave de cache entre permutações de Accept-Encoding. O gzip_vary on do NGINX adiciona automaticamente o cabeçalho Vary único e correto
proxy_read_timeout 30s;
proxy_connect_timeout 10s;
proxy_send_timeout 15s;

Oferece ao origin mais tempo de resposta sob carga, mas ainda falha rapidamente em problemas de conexão.

server {
listen 80 reuseport; # O kernel distribui conexões entre todos os 4 workers
server_name _;
}

reuseport habilita SO_REUSEPORT — o kernel distribui conexões de entrada diretamente aos processos worker, eliminando a contenção de accept mutex.

O simulador injeta cabeçalhos de todos os cinco principais fornecedores CDN simultaneamente. Isso permite que o F5 XC seja configurado com o “Trusted Client IP Header” de qualquer fornecedor e receba payloads de cabeçalho realistas independentemente de qual CDN está sendo simulado.

CabeçalhoValorFinalidade
X-Forwarded-ForCadeia de IPs do clienteIP encaminhado padrão
X-Forwarded-Protohttp ou httpsProtocolo original do cliente
X-Forwarded-HostHostname originalCabeçalho Host original
X-Forwarded-PortPorta do servidorPorta original
X-Real-IPIP do clienteIP único do cliente (convenção nginx)
Via1.1 cdn-simulatorIdentificação do proxy
ForwardedFormato RFC 7239Cabeçalho de encaminhamento padronizado
CDN-Loopcdn-simulatorDetecção de loop
CabeçalhoValorFinalidade
True-Client-IPIP do clienteEndereço IP original do usuário final
X-Akamai-EdgescapeString geo compostageoregion, 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-CharacteristicsPropriedades do dispositivobrand_name, model_name, is_mobile, is_tablet, is_wireless_device, device_os, device_os_version, resolution_width, resolution_height
X-Akamai-Request-IDUUID da requisiçãoIdentificador único de requisição
CabeçalhoValorFinalidade
CF-Connecting-IPIP do clienteIP real do cliente (sempre presente)
CF-IPCountryUSCódigo de país com duas letras
cf-ipcitySan JoseCidade do cliente
cf-ipcontinentNACódigo do continente
cf-iplatitude / cf-iplongitudeCoordenadasGeolocalização
cf-region / cf-region-codeCalifornia / CAInformações de região
cf-metro-code807Código de metrô dos EUA
cf-postal-code95113Código postal
cf-timezoneAmerica/Los_AngelesFuso horário IANA
Cf-Ray{request_id}-SJCRay ID único com código IATA do POP
CF-Visitor{"scheme":"https"}Informação de protocolo do visitante
cf-bot-score85Pontuação de bot (1=bot, 99=humano)
cf-verified-botfalseFlag de bot conhecido e legítimo
cf-ja3-hashe7d705a3286e19ea42f587b344ee6865Fingerprint TLS JA3
cf-ja4t13d1516h2_8daaf6152771_b0da82dd1658Fingerprint TLS JA4
CabeçalhoValorFinalidade
CloudFront-Viewer-AddressIP:portaIP do cliente e porta de origem
CloudFront-Viewer-CountryUSCódigo de país
CloudFront-Viewer-Country-NameUnited StatesNome completo do país
CloudFront-Viewer-Country-RegionCACódigo de região
CloudFront-Viewer-Country-Region-NameCaliforniaNome completo da região
CloudFront-Viewer-CitySan JoseCidade do cliente
CloudFront-Viewer-Postal-Code95113Código postal
CloudFront-Viewer-Latitude / Longitude37.33530 / -121.89300Geolocalização
CloudFront-Viewer-Time-ZoneAmerica/Los_AngelesFuso horário IANA
CloudFront-Viewer-Metro-Code807Código de metrô dos EUA
CloudFront-Viewer-ASN7018Número de Sistema Autônomo
CloudFront-Viewer-Http-Version2.0Versão HTTP do cliente
CloudFront-Forwarded-ProtohttpsProtocolo original
CloudFront-Viewer-TLSTLSv1.3:TLS_AES_128_GCM_SHA256:sessionResumedDetalhes do TLS
CloudFront-Viewer-JA3-Fingerprinte7d705a3286e19ea42f587b344ee6865Fingerprint TLS JA3
CloudFront-Is-Desktop-Viewertrue/falseDetecção de dispositivo
CloudFront-Is-Mobile-Viewertrue/falseDetecção de dispositivo
CloudFront-Is-Tablet-Viewertrue/falseDetecção de dispositivo
CloudFront-Is-SmartTV-ViewerfalseDetecção de dispositivo
X-Amz-Cf-IdID codificadoIdentificador de requisição do CloudFront
CabeçalhoValorFinalidade
Fastly-Client-IPIP do clienteIP real do cliente
Fastly-SSL1Conexão realizada via TLS
Fastly-Client1Requisição voltada ao cliente (não shield)
Fastly-FFcache-sjc3120-SJCIdentificação do nó de cache
X-Geo-Country-CodeUSPaís (convenção de variável VCL)
X-Geo-Country-Code3USACódigo de país com três letras
X-Geo-Country-NameUnited StatesNome completo do país
X-Geo-CitySan JoseCidade do cliente
X-Geo-RegionCACódigo de região
X-Geo-Continent-CodeNAContinente
X-Geo-Latitude / X-Geo-Longitude37.3353 / -121.8938Geolocalização
X-Geo-Postal-Code95113Código postal
X-Geo-Metro-Code807Código de metrô dos EUA
X-Geo-ASN7018Número de Sistema Autônomo
X-Geo-Conn-SpeedbroadbandClasse de velocidade de conexão
X-Geo-Conn-TypewiredTipo de conexão
CabeçalhoValorFinalidade
X-Azure-ClientIPIP do clienteEndereço IP do cliente
X-Azure-SocketIPIP do clienteIP de origem do socket TCP
X-Azure-RefString de referência codificadaReferência única de requisição para diagnóstico
X-Azure-FDIDa0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1Identificador do recurso Front Door
X-Azure-RequestChainhops=1Contagem de saltos para detecção de loop

Cabeçalhos de Resposta (Adicionados às Respostas do Cliente)

Seção intitulada “Cabeçalhos de Resposta (Adicionados às Respostas do Cliente)”
CabeçalhoValoresFinalidade
X-Cache-StatusHIT, MISS, EXPIRED, STALE, UPDATINGComportamento do cache para esta requisição
X-CDN-Edgecdn-simulatorIdentifica este nó de borda
X-CDN-POPSJCCódigo IATA do Point of Presence simulado
X-Served-Bycache-sjc3120-SJCNó de cache simulado no formato Fastly
X-Request-IDUUID (por requisição)Identificador único de requisição

O simulador detecta o tipo de dispositivo a partir do cabeçalho User-Agent usando diretivas map do NGINX:

  • Mobile: Corresponde a iPhone, Android (não tablet), iPod, BlackBerry, Opera Mini, IEMobile
  • Tablet: Corresponde a iPad, Android tablet, Kindle, PlayBook
  • Desktop: Padrão quando nenhum dos anteriores corresponde

O tipo de dispositivo é refletido em:

  • CloudFront-Is-Desktop-Viewer / CloudFront-Is-Mobile-Viewer / CloudFront-Is-Tablet-Viewer
  • X-Akamai-Device-Characteristics (campos is_mobile, is_tablet, is_wireless_device)
Terminal window
ssh azureuser@<PUBLIC_IP>
# Atualizar servidor upstream
sudo sed -i 's|server .*;|server NEW_HOST:80;|' /etc/nginx/conf.d/cdn-edge.conf
# Limpar cache e recarregar
sudo rm -rf /var/cache/nginx/cdn/*
sudo nginx -t && sudo systemctl reload nginx

Ou atualize origin_host em terraform.tfvars e execute terraform apply para reprovisionamento.

Terminal window
ssh azureuser@<PUBLIC_IP>
sudo rm -rf /var/cache/nginx/cdn/*
sudo systemctl reload nginx
Terminal window
# Contagem de objetos e uso de disco
sudo find /var/cache/nginx/cdn -type f | wc -l
sudo du -sh /var/cache/nginx/cdn
# Log de acesso recente com status de cache
tail -20 /var/log/nginx/access.log
Terminal window
# Conexões em tempo real e estados de socket
ss -s
# Uso de CPU dos workers do NGINX
top -bn1 | grep nginx
# Conexões keepalive ao upstream
ss -tn state established dst <ORIGIN_IP> | wc -l
# Contagem de sockets TIME_WAIT
ss -tn state time-wait | wc -l

Verificado em teste de carga contínuo de 48 horas:

MétricaValor
Throughput de pico (em cache)172.540 req/s
Throughput sustentado (em cache)85.000-103.000 req/s
Pico de conexões15.000 simultâneas
Taxa de acerto do cache100% (quando aquecido)
Memória sob carga1,2 GB estável (8% de 16 GB)
CPU no pico100% (4 núcleos — CPU é o teto)
Erros durante o teste de 48h0
Vazamentos de memóriaNenhum detectado
Vazamentos de conexãoNenhum detectado