Nginx se ha consolidado como uno de los servidores web más populares del mundo, especialmente conocido por su alta performance y bajo consumo de recursos. En esta guía aprenderás desde la instalación básica hasta configuraciones avanzadas para entornos de producción.
🎯 Objetivo: Dominar Nginx desde configuraciones básicas hasta técnicas avanzadas de optimización para manejar miles de conexiones concurrentes.
🏗️ Arquitectura de Nginx: ¿Por qué es tan eficiente?
Modelo de procesos: Master + Workers
Nginx utiliza una arquitectura multiproceso que lo hace extremadamente eficiente:
1
2
3
4
5
| Master Process (root)
├── Worker Process 1
├── Worker Process 2
├── Worker Process N
└── Cache Manager Process
|
Master Process:
- Gestiona workers
- Lee configuración
- Maneja señales del sistema
- No procesa conexiones de clientes
Worker Processes:
- Procesan conexiones de clientes
- Un worker por núcleo de CPU (recomendado)
- Event-driven architecture
- Non-blocking I/O
Event-driven vs Thread-based
Apache (tradicional):
1
2
| 1 Thread = 1 Conexión
1000 conexiones = 1000 threads
|
Nginx:
1
2
| 1 Worker = N conexiones (miles)
Event loop maneja todas las conexiones
|
Ventajas del modelo Nginx:
- Menor uso de memoria: No threads por conexión
- Mejor escalabilidad: C10K problem solved
- CPU efficiency: No context switching masivo
📦 Instalación y configuración inicial
Instalación en diferentes distribuciones
Ubuntu/Debian:
1
2
3
4
5
| # Repositorio oficial de Nginx
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
echo "deb https://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install nginx
|
CentOS/RHEL:
1
2
3
4
5
6
7
8
9
10
11
12
| # Añadir repositorio oficial
sudo cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
sudo yum update
sudo yum install nginx
|
Compilación desde fuente (máximo control):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # Dependencias
sudo apt install build-essential libpcre3-dev libssl-dev zlib1g-dev
# Descargar y compilar
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0
# Configurar con módulos específicos
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_gzip_static_module \
--with-http_realip_module
make && sudo make install
|
Estructura de directorios
1
2
3
4
5
6
7
| /etc/nginx/
├── nginx.conf # Configuración principal
├── conf.d/ # Configuraciones adicionales
├── sites-available/ # Sitios disponibles
├── sites-enabled/ # Sitios activos (symlinks)
├── snippets/ # Fragmentos reutilizables
└── ssl/ # Certificados SSL
|
⚙️ Configuración básica optimizada
nginx.conf base para producción
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
| # /etc/nginx/nginx.conf
# Usuario que ejecuta nginx
user nginx;
# Un worker por núcleo de CPU
worker_processes auto;
# Máximo número de file descriptors
worker_rlimit_nofile 65535;
# PID del proceso master
pid /var/run/nginx.pid;
# Configuración de eventos
events {
# Método de manejo de eventos (Linux)
use epoll;
# Conexiones simultáneas por worker
worker_connections 1024;
# Aceptar múltiples conexiones
multi_accept on;
}
http {
# Tipos MIME
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Optimizaciones de red
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Timeouts
keepalive_timeout 65;
client_header_timeout 10;
client_body_timeout 10;
send_timeout 10;
# Buffer sizes
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_max_body_size 20M;
# Compresión Gzip
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/xml+rss
application/json;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# Logs
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# Incluir configuraciones de sitios
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
|
Virtual Host optimizado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
| # /etc/nginx/sites-available/ejemplo.com
server {
listen 80;
listen [::]:80;
server_name ejemplo.com www.ejemplo.com;
# Redirección HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ejemplo.com www.ejemplo.com;
# Directorio raíz
root /var/www/ejemplo.com;
index index.html index.htm index.php;
# SSL Configuration
ssl_certificate /etc/nginx/ssl/ejemplo.com.crt;
ssl_certificate_key /etc/nginx/ssl/ejemplo.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=63072000" always;
# Rate limiting
limit_req zone=api burst=20 nodelay;
limit_conn conn_limit_per_ip 10;
# Cache estatico
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# PHP processing
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
# Cache FastCGI
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
}
# Denegar archivos sensibles
location ~ /\. {
deny all;
}
# Logs específicos del sitio
access_log /var/log/nginx/ejemplo.com.access.log;
error_log /var/log/nginx/ejemplo.com.error.log;
}
|
🚀 Optimización para alta carga
Worker processes y connections
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Cálculo óptimo de workers
worker_processes auto; # Detecta núcleos automáticamente
# O manual:
# worker_processes 4; # Para 4 núcleos
# Conexiones por worker
events {
worker_connections 1024; # Para servidores normales
# worker_connections 4096; # Para alta carga
}
# Límite total teórico = workers × connections
# 4 workers × 1024 = 4096 conexiones simultáneas
|
Configuración de buffers
1
2
3
4
5
6
7
8
9
10
| # Buffers del cliente
client_body_buffer_size 128k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_max_body_size 20M;
# Buffers de proxy
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
|
FastCGI Cache para PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # En el bloque http
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# En el server block
set $skip_cache 0;
# No cachear POST requests
if ($request_method = POST) {
set $skip_cache 1;
}
# No cachear URLs con query
if ($query_string != "") {
set $skip_cache 1;
}
# No cachear admin/login
if ($request_uri ~* "/wp-admin/|/wp-login/") {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache $upstream_cache_status;
# ... resto de configuración PHP
}
|
⚖️ Load Balancing y Reverse Proxy
Configuración básica de upstream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # Definir pool de servidores
upstream backend {
least_conn; # Algoritmo de balanceo
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 weight=1 backup;
# Health checks
server 192.168.1.13:8080 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name api.ejemplo.com;
location / {
proxy_pass http://backend;
# Headers para el backend
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
}
|
Algoritmos de balanceo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # Round Robin (default)
upstream backend {
server server1.com;
server server2.com;
}
# Least Connections
upstream backend {
least_conn;
server server1.com;
server server2.com;
}
# IP Hash (sticky sessions)
upstream backend {
ip_hash;
server server1.com;
server server2.com;
}
# Weighted
upstream backend {
server server1.com weight=3;
server server2.com weight=1;
}
|
🔒 Seguridad avanzada
Rate limiting granular
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # Diferentes zonas de rate limiting
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=general:10m rate=1r/s;
# Aplicar en locations específicos
location /login {
limit_req zone=login burst=2 nodelay;
}
location /api/ {
limit_req zone=api burst=20 nodelay;
}
location / {
limit_req zone=general burst=10 nodelay;
}
|
Bloqueo de IPs maliciosas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Crear mapa de IPs bloqueadas
map $remote_addr $blocked_ip {
default 0;
~^192\.168\.1\.100$ 1;
~^10\.0\.0\.50$ 1;
include /etc/nginx/blocked_ips.conf;
}
server {
# Bloquear IPs maliciosas
if ($blocked_ip) {
return 403;
}
}
|
1
2
3
4
5
6
7
8
9
10
| # Snippet reutilizable: /etc/nginx/snippets/security-headers.conf
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Incluir en server blocks
include /etc/nginx/snippets/security-headers.conf;
|
📊 Monitoreo y logs
Configuración de logs avanzada
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Formato de log personalizado
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time '
'$pipe $connection_requests';
# Logs condicionales
map $status $loggable {
~^[23] 0; # No loggear 2xx, 3xx
default 1; # Loggear errores
}
access_log /var/log/nginx/access.log detailed if=$loggable;
|
Status page para monitoreo
1
2
3
4
5
6
7
8
| # Compilar con --with-http_stub_status_module
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
}
|
Métricas importantes
Comandos de monitoreo:
1
2
3
4
5
6
7
8
9
10
11
| # Conexiones activas
curl -s http://localhost/nginx_status
# Logs en tiempo real
tail -f /var/log/nginx/access.log
# Análisis de performance
awk '{print $NF}' /var/log/nginx/access.log | sort -n | tail -10
# Top IPs
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
|
🛠️ Troubleshooting común
1. Too many open files:
1
2
3
4
5
6
7
8
9
10
11
| # Verificar límites
ulimit -n
# Aumentar en nginx.conf
worker_rlimit_nofile 65535;
# Aumentar systemd limit
sudo systemctl edit nginx
# Añadir:
[Service]
LimitNOFILE=65535
|
2. Alta carga de CPU:
1
2
3
4
5
6
| # Verificar número de workers
ps aux | grep nginx
# Ajustar en nginx.conf
worker_processes auto;
worker_cpu_affinity auto;
|
Debugging de configuración
1
2
3
4
5
6
7
8
| # Test de configuración
sudo nginx -t
# Reload sin downtime
sudo nginx -s reload
# Debug mode
sudo nginx -e /var/log/nginx/debug.log -g 'daemon off;'
|
Análisis de logs de error
1
2
3
4
5
6
7
8
| # Errores más comunes
grep "error" /var/log/nginx/error.log | tail -20
# Conexiones rechazadas
grep "connection refused" /var/log/nginx/error.log
# Timeouts
grep "timeout" /var/log/nginx/error.log
|
🎯 Casos de uso prácticos
WordPress multisite con Nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| map $http_host $blogid {
default 0;
~^site1\.ejemplo\.com$ 1;
~^site2\.ejemplo\.com$ 2;
}
server {
listen 80;
server_name *.ejemplo.com ejemplo.com;
root /var/www/wordpress;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
|
API Gateway con rate limiting
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| upstream api_v1 {
server api1.interno.com:8080;
server api2.interno.com:8080;
}
upstream api_v2 {
server apiv2.interno.com:8080;
}
server {
listen 443 ssl http2;
server_name api.ejemplo.com;
# Rate limiting por endpoint
location /v1/auth {
limit_req zone=login burst=5 nodelay;
proxy_pass http://api_v1;
}
location /v1/ {
limit_req zone=api burst=50 nodelay;
proxy_pass http://api_v1;
}
location /v2/ {
limit_req zone=api burst=100 nodelay;
proxy_pass http://api_v2;
}
}
|
📈 Benchmarking y testing
1
2
3
4
5
6
7
8
| # Apache Bench
ab -n 1000 -c 10 http://ejemplo.com/
# wrk (más avanzado)
wrk -t4 -c100 -d30s http://ejemplo.com/
# siege
siege -c 50 -t 60s http://ejemplo.com/
|
Métricas a monitorear
- Requests per second (RPS)
- Response time (percentiles 50, 95, 99)
- Error rate (4xx, 5xx)
- Connection handling (activas, idle)
- Memory usage por worker
- CPU utilization
🧠 Teoría Avanzada: Fundamentos de Servidores Web
Arquitectura de Redes: El Stack TCP/IP en Nginx
Comprendiendo el flujo completo de una request:
1
| Cliente → DNS → TCP Handshake → TLS Handshake → HTTP Request → Nginx → Backend
|
Cada paso explicado:
1. DNS Resolution:
- Latencia típica: 20-100ms para cold cache
- Optimización: DNS prefetching, CDN con múltiples PoPs
- Nginx role: Server name resolution para upstreams
2. TCP Three-Way Handshake:
1
2
3
| Client → SYN → Server
Client ← SYN+ACK ← Server
Client → ACK → Server
|
- Latencia: 1 RTT (Round Trip Time)
- Optimización Nginx:
tcp_nodelay on
, tcp_nopush on
3. TLS Handshake (HTTPS):
1
2
3
4
| Client → ClientHello → Server
Client ← ServerHello + Certificate ← Server
Client → ClientKeyExchange → Server
Client ← Finished ← Server
|
- Latencia: 2 RTTs para TLS 1.2, 1 RTT para TLS 1.3
- Optimización: Session resumption, OCSP stapling
Event-Driven Architecture: epoll vs select/poll
Evolución de I/O multiplexing:
select() - Generación 1:
1
2
3
4
5
| // Limitaciones: FD_SETSIZE (típicamente 1024)
fd_set readfds, writefds;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
select(sockfd + 1, &readfds, &writefds, NULL, &timeout);
|
- Complejidad: O(n) donde n = número de file descriptors
- Limitación: Máximo 1024 conexiones simultáneas
poll() - Generación 2:
1
2
3
| // Mejora: No límite de FDs, pero sigue siendo O(n)
struct pollfd fds[nfds];
poll(fds, nfds, timeout);
|
- Ventaja: Sin límite artificial de conexiones
- Desventaja: Sigue siendo O(n) para escanear FDs
epoll() - Generación 3 (Linux):
1
2
3
4
| // Event-driven: O(1) para operaciones
int epfd = epoll_create1(0);
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);
epoll_wait(epfd, events, MAX_EVENTS, timeout);
|
- Complejidad: O(1) para operaciones
- Escalabilidad: Maneja millones de conexiones
Implementación en Nginx:
1
2
3
4
5
6
| events {
use epoll; # Linux
# use kqueue; # FreeBSD/macOS
# use /dev/poll; # Solaris
worker_connections 4096;
}
|
Memory Management y CPU Cache Optimization
Worker Process Memory Layout:
1
2
3
4
5
6
7
8
9
| ┌─────────────────┐
│ Code Segment │ ← Shared between workers
├─────────────────┤
│ Data Segment │ ← Configuration, shared memory
├─────────────────┤
│ Heap │ ← Connection pools, buffers
├─────────────────┤
│ Stack │ ← Function calls, local variables
└─────────────────┘
|
CPU Cache Optimization:
1
2
3
4
5
6
| # Bind workers to specific CPU cores
worker_processes auto;
worker_cpu_affinity auto;
# En sistemas con 8 cores:
# worker_cpu_affinity 01 02 04 08 10 20 40 80;
|
Ventajas del CPU affinity:
- Cache locality: Worker mantiene datos en L1/L2 cache del core
- Menos context switching: Reduce overhead del kernel
- NUMA awareness: En sistemas multi-socket
HTTP Protocol Deep Dive
HTTP/1.1 vs HTTP/2 vs HTTP/3:
HTTP/1.1:
1
2
3
4
5
| Características:
- Una request por conexión TCP
- Head-of-line blocking
- Headers en texto plano
- Requiere múltiples conexiones para paralelismo
|
HTTP/2:
1
2
3
4
5
| Mejoras:
- Multiplexing: Múltiples streams por conexión
- Header compression (HPACK)
- Server push
- Stream prioritization
|
HTTP/3 (QUIC):
1
2
3
4
5
| Innovaciones:
- Basado en UDP en lugar de TCP
- Elimina head-of-line blocking a nivel de transporte
- 0-RTT connection establishment
- Built-in encryption
|
Configuración Nginx para HTTP/2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| server {
listen 443 ssl http2;
# HTTP/2 optimizations
http2_max_field_size 16k;
http2_max_header_size 32k;
http2_max_requests 1000;
# Server push (experimental)
location / {
http2_push /css/styles.css;
http2_push /js/app.js;
}
}
|
Load Balancing Algorithms: Teoría y Práctica
Round Robin:
1
2
3
4
5
6
7
8
9
10
11
| Algoritmo: request_n % server_count
Complejidad: O(1)
Uso de memoria: O(1)
Ventajas:
- Simple y predecible
- Distribución uniforme en cargas similares
Desventajas:
- No considera carga actual del servidor
- Problemas con sesiones sticky
|
Least Connections:
1
2
3
4
5
6
7
8
9
10
11
| Algoritmo: min(active_connections_per_server)
Complejidad: O(n) donde n = número de servidores
Uso de memoria: O(n)
Ventajas:
- Considera carga actual
- Mejor para requests de duración variable
Desventajas:
- Más overhead computacional
- Estado compartido entre workers
|
IP Hash:
1
2
3
4
5
6
7
8
9
10
11
| Algoritmo: hash(client_ip) % server_count
Complejidad: O(1)
Uso de memoria: O(1)
Ventajas:
- Sticky sessions automáticas
- Cacheable per-user
Desventajas:
- Distribución desigual con NAT
- Problemas con failover
|
Weighted Round Robin:
1
2
3
4
5
6
7
| upstream backend {
server backend1.example.com weight=3;
server backend2.example.com weight=2;
server backend3.example.com weight=1;
}
# Secuencia: backend1, backend1, backend2, backend1, backend2, backend3
|
Cipher Suite Selection:
1
2
3
4
5
6
7
8
| # Orden de preferencia de ciphers
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
# Explicación:
# ECDHE: Perfect Forward Secrecy
# ECDSA vs RSA: ECDSA más eficiente
# AES256-GCM: Authenticated encryption
# CHACHA20: Alternativa para móviles
|
Session Resumption:
1
2
3
4
5
6
7
| # Session tickets (stateless)
ssl_session_tickets on;
ssl_session_ticket_key /etc/nginx/ssl/ticket.key;
# Session cache (stateful)
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
|
OCSP Stapling:
1
2
3
4
5
| # Reduce TLS handshake latency
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/ca-chain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
|
Cache Theory y Implementación
Cache Hierarchy:
1
| Browser Cache → CDN Cache → Nginx Cache → Application Cache → Database
|
Cache Headers Strategy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
# Static assets - long cache
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
}
location /api/ {
# API responses - conditional cache
add_header Cache-Control "private, max-age=300";
add_header ETag $request_id;
}
location /dynamic/ {
# Dynamic content - no cache
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
|
FastCGI Cache Algorithm:
1
2
3
4
5
6
7
| Cache Key = MD5(scheme + request_method + host + request_uri + args)
Lookup Process:
1. Hash cache key
2. Check memory index
3. If hit: serve from memory/disk
4. If miss: request from backend + store
|
🎓 Conclusión
Nginx es una herramienta extremadamente poderosa que, con la configuración correcta, puede manejar cargas masivas con recursos mínimos. La comprensión profunda de su arquitectura event-driven, la teoría de redes subyacente y los algoritmos de optimización es lo que separa una configuración básica de una implementación de nivel empresarial.
Las claves del éxito son:
- Entender la arquitectura event-driven y sus implicaciones
- Optimizar para tu caso de uso específico basado en patrones de tráfico
- Monitorear constantemente el rendimiento y ajustar dinámicamente
- Aplicar seguridad desde el primer día con defense-in-depth
- Testing regular de configuraciones bajo carga real
- Comprender la teoría subyacente para troubleshooting efectivo
Próximos pasos recomendados
- Implementar Nginx Plus para features empresariales
- Integrar con Prometheus/Grafana para monitoreo avanzado
- Explorar OpenResty para funcionalidad con Lua scripting
- Configurar WAF (Web Application Firewall) con ModSecurity
- Estudiar HTTP/3 y QUIC para prepararse para el futuro
El dominio de Nginx no es solo sobre configuración, sino sobre entender cómo funcionan los sistemas distribuidos modernos a gran escala.
Andrés Nuñez - t4ifi