- Início
- Simulador CDN
- Configuração do NGINX
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.
Arquivos de Configuração
Seção intitulada “Arquivos de Configuração”| Arquivo | Finalidade |
|---|---|
/etc/sysctl.d/99-cdn-tuning.conf | Ajuste de rede do kernel Linux |
/etc/systemd/system/nginx.service.d/override.conf | Limites de descritores de arquivo para o NGINX |
/etc/security/limits.d/99-nginx.conf | Limites no nível do SO para o usuário www-data |
/etc/nginx/nginx.conf | Configuração principal do NGINX (workers, buffers, gzip, logging) |
/etc/nginx/conf.d/cdn-edge.conf | Configuração de proxy CDN (cache, upstream, cabeçalhos) |
Ajuste do Kernel
Seção intitulada “Ajuste do Kernel”Aplicado via /etc/sysctl.d/99-cdn-tuning.conf na inicialização.
| Parâmetro | Valor | Padrão | Finalidade |
|---|---|---|---|
net.core.somaxconn | 65535 | 4096 | Tamanho da fila de backlog de escuta |
net.core.netdev_max_backlog | 65535 | 1000 | Backlog de pacotes de entrada por CPU |
net.ipv4.tcp_max_syn_backlog | 65535 | 256 | Fila de requisições SYN (evita descartes em rajadas) |
net.ipv4.tcp_tw_reuse | 1 | 2 | Reutilizar sockets TIME_WAIT para conexões de saída |
net.ipv4.ip_local_port_range | 1024-65535 | 32768-60999 | Intervalo de portas efêmeras (64K vs 28K) |
net.core.rmem_max | 16 MB | 212 KB | Buffer máximo de recepção do socket |
net.core.wmem_max | 16 MB | 212 KB | Buffer máximo de envio do socket |
net.ipv4.tcp_rmem | 4K/87K/16M | 4K/131K/6M | Buffer de recepção por socket (mín/padrão/máx) |
net.ipv4.tcp_wmem | 4K/65K/16M | 4K/16K/4M | Buffer de envio por socket (mín/padrão/máx) |
net.ipv4.tcp_fin_timeout | 15 | 60 | Timeout FIN_WAIT_2 (limpeza mais rápida de sockets) |
net.ipv4.tcp_keepalive_time | 300 | 7200 | Iniciar probes de keepalive após 5 min de ociosidade |
net.ipv4.tcp_slow_start_after_idle | 0 | 1 | Manter a janela de congestionamento aquecida em conexões ociosas |
net.ipv4.tcp_max_tw_buckets | 2000000 | ~65536 | Máximo de sockets TIME_WAIT |
fs.file-max | 2097152 | varia | Limite de descritores de arquivo em todo o sistema |
vm.swappiness | 10 | 60 | Preferir RAM ao swap para dados em cache |
Configuração Principal do NGINX
Seção intitulada “Configuração Principal do NGINX”Workers e Conexões
Seção intitulada “Workers e Conexões”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.
Buffers de Proxy
Seção intitulada “Buffers de Proxy”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.
Compressão Gzip
Seção intitulada “Compressão Gzip”gzip on;gzip_comp_level 4; # Equilíbrio: ~85% da compressão máxima com ~40% de CPUgzip_min_length 256; # Ignora respostas pequenas (overhead do cabeçalho gzip)gzip_vary on; # Vary: Accept-Encoding para caching corretogzip_proxied any; # Comprime todas as respostas proxiadasgzip_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 de Arquivos Abertos
Seção intitulada “Cache de Arquivos Abertos”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 do Cliente
Seção intitulada “Keepalive do Cliente”keepalive_timeout 65;keepalive_requests 100000; # Era 1000 — causava reciclagem de conexões a 90K req/sA 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 de Acesso
Seção intitulada “Log de Acesso”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.
Keepalive de Upstream
Seção intitulada “Keepalive de Upstream”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.
Configuração de Cache
Seção intitulada “Configuração de Cache”Caminho do Cache
Seção intitulada “Caminho do 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;| Parâmetro | Valor | Finalidade |
|---|---|---|
keys_zone=cdn_cache:32m | 32 MB de memória compartilhada | Armazena ~256.000 chaves de cache e metadados |
max_size=25g | Limite de disco de 25 GB | Utiliza a maior parte do disco de 30 GB do SO; evição LRU ao atingir o limite |
inactive=24h | Timeout de inatividade de 24 horas | Conteúdo não acessado por 24h é evicado (diferente do TTL) |
use_temp_path=off | Grava diretamente no diretório de cache | Evita movimentação de arquivos entre sistemas de arquivos |
Comportamento do Cache
Seção intitulada “Comportamento do 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;| Diretiva | Valor | Finalidade |
|---|---|---|
proxy_cache_valid 200 301 302 4h | TTL de 4 horas | Conteúdo em cache válido por 4 horas (aumentado para reduzir quedas de throughput durante onda de atualização) |
proxy_cache_lock on | Prevenção de thundering herd | Apenas 1 requisição vai ao origin por URL não cacheada; as demais aguardam o preenchimento do cache |
proxy_cache_lock_age 3s | Timeout de lock | Se a primeira requisição não foi concluída em 3s, permite outra passar |
proxy_cache_background_update on | Atualização sem latência | Serve conteúdo stale imediatamente enquanto atualiza em segundo plano |
proxy_cache_use_stale | Resiliência | Serve conteúdo stale durante erros do origin (500/502/503/504) ou durante atualização |
proxy_ignore_headers | Forçar caching | Ignora 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-Status | Remover cabeçalho do origin | O 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 Vary | Evitar fragmentação do cache | O 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 |
Timeouts de Proxy
Seção intitulada “Timeouts de Proxy”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.
Bloco de Servidor
Seção intitulada “Bloco de Servidor”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.
Cabeçalhos de Fornecedores CDN
Seção intitulada “Cabeçalhos de Fornecedores CDN”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çalhos Padrão da Indústria (Todos os CDNs)
Seção intitulada “Cabeçalhos Padrão da Indústria (Todos os CDNs)”| Cabeçalho | Valor | Finalidade |
|---|---|---|
X-Forwarded-For | Cadeia de IPs do cliente | IP encaminhado padrão |
X-Forwarded-Proto | http ou https | Protocolo original do cliente |
X-Forwarded-Host | Hostname original | Cabeçalho Host original |
X-Forwarded-Port | Porta do servidor | Porta original |
X-Real-IP | IP do cliente | IP único do cliente (convenção nginx) |
Via | 1.1 cdn-simulator | Identificação do proxy |
Forwarded | Formato RFC 7239 | Cabeçalho de encaminhamento padronizado |
CDN-Loop | cdn-simulator | Detecção de loop |
Cabeçalhos Akamai
Seção intitulada “Cabeçalhos Akamai”| Cabeçalho | Valor | Finalidade |
|---|---|---|
True-Client-IP | IP do cliente | Endereço IP original do usuário final |
X-Akamai-Edgescape | String 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 | Propriedades do 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 da requisição | Identificador único de requisição |
Cabeçalhos Cloudflare
Seção intitulada “Cabeçalhos Cloudflare”| Cabeçalho | Valor | Finalidade |
|---|---|---|
CF-Connecting-IP | IP do cliente | IP real do cliente (sempre presente) |
CF-IPCountry | US | Código de país com duas letras |
cf-ipcity | San Jose | Cidade do cliente |
cf-ipcontinent | NA | Código do continente |
cf-iplatitude / cf-iplongitude | Coordenadas | Geolocalização |
cf-region / cf-region-code | California / CA | Informações de região |
cf-metro-code | 807 | Código de metrô dos EUA |
cf-postal-code | 95113 | Código postal |
cf-timezone | America/Los_Angeles | Fuso horário IANA |
Cf-Ray | {request_id}-SJC | Ray ID único com código IATA do POP |
CF-Visitor | {"scheme":"https"} | Informação de protocolo do visitante |
cf-bot-score | 85 | Pontuação de bot (1=bot, 99=humano) |
cf-verified-bot | false | Flag de bot conhecido e legítimo |
cf-ja3-hash | e7d705a3286e19ea42f587b344ee6865 | Fingerprint TLS JA3 |
cf-ja4 | t13d1516h2_8daaf6152771_b0da82dd1658 | Fingerprint TLS JA4 |
Cabeçalhos Amazon CloudFront
Seção intitulada “Cabeçalhos Amazon CloudFront”| Cabeçalho | Valor | Finalidade |
|---|---|---|
CloudFront-Viewer-Address | IP:porta | IP do cliente e porta de origem |
CloudFront-Viewer-Country | US | Código de país |
CloudFront-Viewer-Country-Name | United States | Nome completo do país |
CloudFront-Viewer-Country-Region | CA | Código de região |
CloudFront-Viewer-Country-Region-Name | California | Nome completo da região |
CloudFront-Viewer-City | San Jose | Cidade do cliente |
CloudFront-Viewer-Postal-Code | 95113 | Código postal |
CloudFront-Viewer-Latitude / Longitude | 37.33530 / -121.89300 | Geolocalização |
CloudFront-Viewer-Time-Zone | America/Los_Angeles | Fuso horário IANA |
CloudFront-Viewer-Metro-Code | 807 | Código de metrô dos EUA |
CloudFront-Viewer-ASN | 7018 | Número de Sistema Autônomo |
CloudFront-Viewer-Http-Version | 2.0 | Versão HTTP do cliente |
CloudFront-Forwarded-Proto | https | Protocolo original |
CloudFront-Viewer-TLS | TLSv1.3:TLS_AES_128_GCM_SHA256:sessionResumed | Detalhes do TLS |
CloudFront-Viewer-JA3-Fingerprint | e7d705a3286e19ea42f587b344ee6865 | Fingerprint TLS JA3 |
CloudFront-Is-Desktop-Viewer | true/false | Detecção de dispositivo |
CloudFront-Is-Mobile-Viewer | true/false | Detecção de dispositivo |
CloudFront-Is-Tablet-Viewer | true/false | Detecção de dispositivo |
CloudFront-Is-SmartTV-Viewer | false | Detecção de dispositivo |
X-Amz-Cf-Id | ID codificado | Identificador de requisição do CloudFront |
Cabeçalhos Fastly
Seção intitulada “Cabeçalhos Fastly”| Cabeçalho | Valor | Finalidade |
|---|---|---|
Fastly-Client-IP | IP do cliente | IP real do cliente |
Fastly-SSL | 1 | Conexão realizada via TLS |
Fastly-Client | 1 | Requisição voltada ao cliente (não shield) |
Fastly-FF | cache-sjc3120-SJC | Identificação do nó de cache |
X-Geo-Country-Code | US | País (convenção de variável VCL) |
X-Geo-Country-Code3 | USA | Código de país com três letras |
X-Geo-Country-Name | United States | Nome completo do país |
X-Geo-City | San Jose | Cidade do cliente |
X-Geo-Region | CA | Código de região |
X-Geo-Continent-Code | NA | Continente |
X-Geo-Latitude / X-Geo-Longitude | 37.3353 / -121.8938 | Geolocalização |
X-Geo-Postal-Code | 95113 | Código postal |
X-Geo-Metro-Code | 807 | Código de metrô dos EUA |
X-Geo-ASN | 7018 | Número de Sistema Autônomo |
X-Geo-Conn-Speed | broadband | Classe de velocidade de conexão |
X-Geo-Conn-Type | wired | Tipo de conexão |
Cabeçalhos Azure Front Door
Seção intitulada “Cabeçalhos Azure Front Door”| Cabeçalho | Valor | Finalidade |
|---|---|---|
X-Azure-ClientIP | IP do cliente | Endereço IP do cliente |
X-Azure-SocketIP | IP do cliente | IP de origem do socket TCP |
X-Azure-Ref | String de referência codificada | Referência única de requisição para diagnóstico |
X-Azure-FDID | a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1 | Identificador do recurso Front Door |
X-Azure-RequestChain | hops=1 | Contagem 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çalho | Valores | Finalidade |
|---|---|---|
X-Cache-Status | HIT, MISS, EXPIRED, STALE, UPDATING | Comportamento do cache para esta requisição |
X-CDN-Edge | cdn-simulator | Identifica este nó de borda |
X-CDN-POP | SJC | Código IATA do Point of Presence simulado |
X-Served-By | cache-sjc3120-SJC | Nó de cache simulado no formato Fastly |
X-Request-ID | UUID (por requisição) | Identificador único de requisição |
Detecção de Dispositivos
Seção intitulada “Detecção de Dispositivos”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-ViewerX-Akamai-Device-Characteristics(camposis_mobile,is_tablet,is_wireless_device)
Operações
Seção intitulada “Operações”Alterando o Servidor de Origin
Seção intitulada “Alterando o Servidor de Origin”ssh azureuser@<PUBLIC_IP>
# Atualizar servidor upstreamsudo sed -i 's|server .*;|server NEW_HOST:80;|' /etc/nginx/conf.d/cdn-edge.conf
# Limpar cache e recarregarsudo rm -rf /var/cache/nginx/cdn/*sudo nginx -t && sudo systemctl reload nginxOu atualize origin_host em terraform.tfvars e execute terraform apply para reprovisionamento.
Limpando o Cache
Seção intitulada “Limpando o Cache”ssh azureuser@<PUBLIC_IP>sudo rm -rf /var/cache/nginx/cdn/*sudo systemctl reload nginxVerificando Estatísticas do Cache
Seção intitulada “Verificando Estatísticas do Cache”# Contagem de objetos e uso de discosudo find /var/cache/nginx/cdn -type f | wc -lsudo du -sh /var/cache/nginx/cdn
# Log de acesso recente com status de cachetail -20 /var/log/nginx/access.logMonitoramento sob Carga
Seção intitulada “Monitoramento sob Carga”# Conexões em tempo real e estados de socketss -s
# Uso de CPU dos workers do NGINXtop -bn1 | grep nginx
# Conexões keepalive ao upstreamss -tn state established dst <ORIGIN_IP> | wc -l
# Contagem de sockets TIME_WAITss -tn state time-wait | wc -lResultados do Benchmark de Desempenho
Seção intitulada “Resultados do Benchmark de Desempenho”Verificado em teste de carga contínuo de 48 horas:
| Métrica | Valor |
|---|---|
| Throughput de pico (em cache) | 172.540 req/s |
| Throughput sustentado (em cache) | 85.000-103.000 req/s |
| Pico de conexões | 15.000 simultâneas |
| Taxa de acerto do cache | 100% (quando aquecido) |
| Memória sob carga | 1,2 GB estável (8% de 16 GB) |
| CPU no pico | 100% (4 núcleos — CPU é o teto) |
| Erros durante o teste de 48h | 0 |
| Vazamentos de memória | Nenhum detectado |
| Vazamentos de conexão | Nenhum detectado |