Entrada

Apache vs Nginx: Guía Completa para Elegir el Servidor Web Correcto

Apache vs Nginx: Guía Completa para Elegir el Servidor Web Correcto

Apache vs Nginx: Guía Completa para Elegir el Servidor Web Correcto

En el mundo de los servidores web, Apache HTTP Server y Nginx dominan el panorama. Entender las diferencias entre estos dos gigantes es crucial para tomar decisiones arquitectónicas correctas.

Introducción a los Servidores Web

¿Qué es un Servidor Web?

Un servidor web es un software que acepta peticiones HTTP de clientes (navegadores) y responde con páginas web, archivos o datos. Actúa como intermediario entre el usuario y la aplicación.

Componentes de un Servidor Web:

  • Motor HTTP: Procesa peticiones y respuestas
  • Gestión de conexiones: Maneja múltiples clientes simultáneos
  • Módulos: Extienden funcionalidad
  • Configuración: Define comportamiento y reglas

Apache HTTP Server: El Veterano

Historia y Filosofía

Apache fue lanzado en 1995 y se convirtió en el servidor web más popular durante años. Su enfoque modular y flexibilidad lo hicieron dominante en los primeros días de la web.

Arquitectura de Apache

Modelo de Procesos Múltiples (MPM)

1
2
3
4
5
6
7
8
9
10
11
# Verificar MPM activo
apache2ctl -V | grep MPM

# Prefork MPM (un proceso por conexión)
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

# Worker MPM (híbrido procesos/threads)
LoadModule mpm_worker_module modules/mod_mpm_worker.so

# Event MPM (asíncrono)
LoadModule mpm_event_module modules/mod_mpm_event.so

Configuración de Prefork MPM

1
2
3
4
5
6
7
8
<IfModule mpm_prefork_module>
    StartServers             8
    MinSpareServers          5
    MaxSpareServers         20
    ServerLimit            256
    MaxRequestWorkers      256
    MaxConnectionsPerChild   0
</IfModule>

Ventajas de Apache

1. Sistema de Módulos Robusto

1
2
3
4
5
6
7
8
9
10
# Listar módulos disponibles
apache2ctl -M

# Habilitar módulo
a2enmod rewrite
a2enmod ssl
a2enmod headers

# Deshabilitar módulo
a2dismod status

2. Archivo .htaccess

1
2
3
4
5
6
7
8
9
10
11
12
13
# .htaccess para reescritura de URLs
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

# Configuración de cache
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
</IfModule>

3. Virtual Hosts Flexibles

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
    ServerName ejemplo.com
    DocumentRoot /var/www/ejemplo
    
    <Directory /var/www/ejemplo>
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog ${APACHE_LOG_DIR}/ejemplo_error.log
    CustomLog ${APACHE_LOG_DIR}/ejemplo_access.log combined
</VirtualHost>

Configuración Avanzada de Apache

SSL/TLS con Apache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<VirtualHost *:443>
    ServerName ejemplo.com
    DocumentRoot /var/www/ejemplo
    
    SSLEngine on
    SSLCertificateFile /path/to/certificate.crt
    SSLCertificateKeyFile /path/to/private.key
    SSLCertificateChainFile /path/to/chain.crt
    
    # Configuración de seguridad SSL
    SSLProtocol all -SSLv2 -SSLv3
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder on
</VirtualHost>

Nginx: El Innovador

Historia y Filosofía

Nginx fue creado en 2004 por Igor Sysoev para resolver el “problema C10K” (manejar 10,000 conexiones concurrentes). Su arquitectura asíncrona lo hace extremadamente eficiente.

Arquitectura de Nginx

Modelo Event-Driven

1
2
3
4
5
6
# Verificar configuración de workers
nginx -t
ps aux | grep nginx

# worker_processes auto configura automáticamente
# según el número de CPUs

Configuración Principal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
}

Ventajas de Nginx

1. Alto Rendimiento

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Configuración optimizada para performance
worker_rlimit_nofile 65535;

events {
    worker_connections 8192;
    use epoll;
    multi_accept on;
}

http {
    # Buffer optimization
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
    output_buffers 1 32k;
    postpone_output 1460;
}

2. Proxy Reverso Eficiente

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
upstream backend {
    least_conn;
    server 127.0.0.1:8000 weight=3;
    server 127.0.0.1:8001 weight=2;
    server 127.0.0.1:8002 backup;
}

server {
    listen 80;
    server_name ejemplo.com;
    
    location / {
        proxy_pass http://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;
    }
}

3. Load Balancing Avanzado

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream app_servers {
    # Métodos de balanceo
    ip_hash;  # Sesiones sticky
    # least_conn;  # Menos conexiones
    # random;  # Aleatorio
    
    server app1.ejemplo.com:8000 max_fails=3 fail_timeout=30s;
    server app2.ejemplo.com:8000 max_fails=3 fail_timeout=30s;
    server app3.ejemplo.com:8000 backup;
    
    # Health checks (Nginx Plus)
    # health_check;
}

Comparación Detallada

Rendimiento

Manejo de Conexiones Concurrentes

1
2
3
4
5
# Test de concurrencia con Apache Bench
ab -n 10000 -c 100 http://servidor/

# Nginx típicamente maneja más conexiones con menos recursos
# Apache consume más memoria por conexión

Uso de Memoria

  • Apache: ~15MB por proceso worker
  • Nginx: ~2-4MB total para todos los workers

Configuración

Apache (.htaccess vs nginx.conf)

1
2
3
# Apache .htaccess (distribuido)
RewriteEngine On
RewriteRule ^api/(.*)$ /api.php?request=$1 [QSA,L]
1
2
3
4
# Nginx (centralizado)
location ~* ^/api/(.*)$ {
    rewrite ^/api/(.*)$ /api.php?request=$1 last;
}

Módulos y Extensibilidad

Apache: Módulos Dinámicos

1
2
3
4
5
6
# Instalar módulo
apt-get install libapache2-mod-php
a2enmod php7.4

# Módulos personalizados en C
# Más fácil desarrollo de módulos

Nginx: Módulos Estáticos

1
2
3
4
5
# Compilar con módulos
./configure --with-http_ssl_module --with-http_gzip_module

# Módulos de terceros requieren recompilación
# (excepto en versiones comerciales)

Casos de Uso Específicos

Cuándo Usar Apache

1. Shared Hosting

1
2
3
4
5
# .htaccess permite control granular por usuario
<Directory /home/usuario/public_html>
    AllowOverride All
    php_admin_value open_basedir /home/usuario
</Directory>

2. Aplicaciones Legacy

1
2
3
# Soporte extensivo para tecnologías antiguas
LoadModule cgi_module modules/mod_cgi.so
LoadModule perl_module modules/mod_perl.so

3. Desarrollo Rápido

1
2
# Configuración inmediata sin restart
# .htaccess cambios en tiempo real

Cuándo Usar Nginx

1. Alto Tráfico

1
2
3
4
5
# Optimizado para muchas conexiones simultáneas
events {
    worker_connections 8192;
    use epoll;
}

2. Microservicios

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Excelente como API Gateway
upstream auth_service {
    server auth:8001;
}

upstream user_service {
    server users:8002;
}

location /api/auth/ {
    proxy_pass http://auth_service/;
}

location /api/users/ {
    proxy_pass http://user_service/;
}

3. Contenido Estático

1
2
3
4
5
6
# Servir archivos estáticos eficientemente
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

Configuraciones Híbridas

Nginx como Frontend + Apache como Backend

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# nginx.conf
upstream apache_backend {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name ejemplo.com;
    
    # Contenido estático con Nginx
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
        root /var/www/html;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # Contenido dinámico con Apache
    location / {
        proxy_pass http://apache_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
1
2
3
4
5
6
7
8
9
10
11
# Apache en puerto 8080
Listen 8080
<VirtualHost *:8080>
    ServerName ejemplo.com
    DocumentRoot /var/www/html
    
    # Solo procesamiento dinámico
    <LocationMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg)$">
        Require all denied
    </LocationMatch>
</VirtualHost>

Optimización y Tuning

Apache Performance Tuning

MPM Event Optimization

1
2
3
4
5
6
7
<IfModule mpm_event_module>
    ServerLimit              16
    MaxRequestWorkers       400
    ThreadsPerChild          25
    ThreadLimit              64
    AsyncRequestWorkerFactor 2
</IfModule>

Cache Configuration

1
2
3
4
5
6
7
8
9
10
# mod_cache_disk
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so

<IfModule mod_cache.c>
    CacheEnable disk /
    CacheRoot /var/cache/apache2/mod_cache_disk
    CacheDirLevels 2
    CacheDirLength 1
</IfModule>

Nginx Performance Tuning

Worker Optimization

1
2
3
4
5
6
7
8
9
10
11
# Ajustar según hardware
worker_processes auto;
worker_rlimit_nofile 65535;
worker_cpu_affinity auto;

events {
    worker_connections 8192;
    use epoll;
    multi_accept on;
    accept_mutex off;
}

Gzip Compression

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/rss+xml
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/svg+xml
    image/x-icon
    text/css
    text/plain
    text/x-component;

Monitoreo y Debugging

Apache Monitoring

1
2
3
4
5
6
7
# mod_status habilitado
curl http://localhost/server-status
curl http://localhost/server-status?auto

# Logs detallados
LogLevel debug
CustomLog logs/access.log "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D"

Nginx Monitoring

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# stub_status module
location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

# Logs personalizados
log_format detailed '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   '$request_time $upstream_response_time';

access_log /var/log/nginx/detailed.log detailed;

Conclusiones y Recomendaciones

Matriz de Decisión

CriterioApacheNginx
Facilidad de configuración⭐⭐⭐⭐⭐⭐⭐⭐
Performance alta concurrencia⭐⭐⭐⭐⭐⭐⭐⭐
Uso de memoria⭐⭐⭐⭐⭐⭐⭐
Flexibilidad módulos⭐⭐⭐⭐⭐⭐⭐⭐
Soporte .htaccess⭐⭐⭐⭐⭐
Load balancing⭐⭐⭐⭐⭐⭐⭐⭐
Documentación⭐⭐⭐⭐⭐⭐⭐⭐⭐

Recomendaciones Finales

  1. Para desarrollo y shared hosting: Apache
  2. Para alta concurrencia y microservicios: Nginx
  3. Para máxima flexibilidad: Apache
  4. Para mejor performance: Nginx
  5. Para configuración híbrida: Nginx + Apache

La elección entre Apache y Nginx no es binaria. Muchas arquitecturas modernas combinan ambos, aprovechando las fortalezas de cada uno.


Andrés Nuñez - t4ifi

Esta entrada está licenciada bajo CC BY 4.0 por el autor.