¿Cómo configurar Nginx para obtener un rendimiento óptimo?
Actualizado el 5 de octubre, 2016. Por BlueHosting.
El servidor web Nginx se ha popularizado en los últimos años tanto por su alto desempeño en el balance de carga y el almacenamiento en caché de contenido web dinámico y estático. Esta guía pretende proporcionar algunos consejos para determinar las mejores optimizaciones de rendimiento necesarias en un servidor Nginx para acelerar la entrega de contenido a sus usuarios finales.
Modificaciones del Worker
Una de las modificaciones más sencillas que puede hacer en su configuración es establecer el número adecuado de conexiones y workers.
Procesos Worker
Si usted tiene un tráfico bajo en su sitio web y además nginx, su base de datos y la aplicación web todos se ejecutan en el mismo servidor entonces abra el archivo /etc/nginx/nginx.conf
y establezca el valor:
worker_processes 1;
Si en cambio tiene un tráfico alto o una instancia dedicada para Nginx, fije un worker por cada core del CPU:
worker_processes auto;
Si desea configurar esto de forma manual, puede usar grep ^processor /proc/cpuinfo | wc -l
para encontrar el número de procesos que el servidor puede manejar.
Conexiones Worker
La opción worker_connections
establece el número máximo de conexiones que cada proceso worker puede procesar a la vez. Por defecto, el límite de este valor es 512 pero muchos sistemas pueden manejar valores más altos.
El tamaño apropiado puede ser descubierto a través de pruebas y es variable con base en el tipo de tráfico que maneje Nginx. Las limitaciones en el core del sistema también pueden encontrarse usando la utilidad ulimit
:
ulimit -n
Esto imprimirá un número como resultado:
65536
También puede definir use epoll
, un mecanismo escalable de notificación de eventos de Entrada/Salida (I/O) que se activa en la ocurrencia de ciertos eventos, asegurándose de que el I/O es utilizado en su mejor capacidad.
Por último, puede usar multi_accept
con el fin de que un worker acepte todas las nuevas conexiones al mismo tiempo.
La función events
debería lucir similar a la siguiente cuando se configure:
Extracto del archivo: /etc/nginx/nginx.conf
events {
worker_connections 66536;
use epoll;
multi_accept on;
}
Optimizaciones HTTP y TCP
KeepAlive
La opción Keep Alive (mantener vivo) permite un menor número de reconexiones desde el navegador.
- Los parámetros
keepalive_timeout
ykeepalive_requests
controlan los ajustes keep alive. sendfile
optimiza la entrega de archivos estáticos desde el sistema de archivos, por ejemplo: logotipos.tcp_nodelay
permite que Nginx haga que TCP envíe varios búferes como paquetes individuales.tcp_nopush
optimiza la cantidad de datos enviados en línea a la vez, activando la opciónTCP_CORK
dentro de la infraestructura TCP.TCP_CORK
bloquea los datos hasta que el paquete haya alcanzado el MSS, lo que es equivalente al MTU menos los 40 o 60 bytes de la cabecera IP.
Extracto del archivo: /etc/nginx/nginx.conf
keepalive_timeout 65;
keepalive_requests 100000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
Tamaño del búfer
Hacer algunos ajustes al tamaño del búfer puede ser muy ventajoso. Si los tamaños del búfer son demasiado bajos, entonces Nginx escribirá en un archivo temporal. Esto es causado por un exceso de I/O en el disco.
- El parámetro
client_body_buffer_size
controla el tamaño del búfer del cliente. La mayoría de los búferes de los clientes vienen del método POST en los envíos de formularios.128k
es generalmente un buen valor para esta opción. client_max_body_size
establece el tamaño máximo del cuerpo del búfer. Si el tamaño en una solicitud excede el valor configurado en este parámetro, se le devolverá el siguiente error al cliente: 413 (Request Entity Too Large —la entidad solicitada es demasiado grande). Para su referencia, los navegadores no pueden mostrar los errores 413 correctamente. Establecer el tamaño en 0 deshabilita el chequeo de la solicitud del tamaño del cuerpo de búfer del cliente.client_header_buffer_size
maneja el tamaño de la cabecera asignada al cliente. En general,1k
es una selección bastante sana para este valor.large_client_header_buffers
muestra el número máximo y el tamaño de los búferes para cabeceras más grandes de clientes. 4 cabeceras con búferes de4k
deberían ser suficientes aquí.output_buffers
establece el número y el tamaño de los búferes utilizados para leer una respuesta en disco. Si es posible, la transmisión de los datos del cliente será pospuesta hasta que Nginx tenga establecido al menos el tamaño de bytes de datos a enviar. El valor cero desactiva el aplazamiento en la transmisión de datos.
Extracto del archivo: /etc/nginx/nginx.conf
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;
Cola de conexión
Algunas directivas en el archivo /etc/sysctl.conf
pueden ser cambiadas para establecer el tamaño de una cola de Linux para las conexiones y los buckets. Actualizar los parámetros net.core.somaxconn
y net.ipv4.tcp_max_tw_buckets
cambia el tamaño de la cola para las conexiones esperando ser aceptadas por Nginx. Si hay mensajes de error en el log del kernel, aumente el valor hasta que el error desaparezca.
Extracto del archivo: /etc/sysctl.conf
net.core.somaxconn = 65536
net.ipv4.tcp_max_tw_buckets = 1440000
Los paquetes pueden ser almacenados en el búfer de la tarjeta de antes de ser enviados al CPU. Esto se logra estableciendo la reserva máxima con la etiqueta net.core.netdev_max_backlog
. Consulte la documentación de la tarjeta de red en busca de consejos sobre el cambio de este valor.
Timeouts
Los tiempos de espera o timeouts puede mejorar el rendimiento drásticamente.
- La opción
client_body_timeout
envía directivas por el tiempo en el que un servidor esperará que un cuerpo sea enviado. client_header_timeout
envía directivas por el tiempo en el que un servidor esperará que una cabecera sea enviada. Estas directivas son responsables por el tiempo en el que un servidor esperará que un cuerpo o cabecera del cliente sea enviado después de una solicitud. Si no se envía ningún cuerpo o cabecera, el servidor emitirá un error 408 "Tiempo de espera de solicitud agotado" (Request time out).sent_timeout
especifica el tiempo de espera de la respuesta al cliente. Este timeout no aplica a la transferencia completa, más bien mide únicamente dos operaciones sucesivas de lectura en el cliente.
Extracto del archivo: /etc/nginx/nginx.conf
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
Entrega de recursos estáticos
Si su sitio entrega recursos estáticos (tales como: CSS, JavaScript e imágenes), Nginx puede almacenar estos archivos en caché por un corto período de tiempo. Añadir esto dentro de su bloque de configuración le dice Nginx que almacene un máximo de 1000 archivos en caché durante 30 segundos, excluyendo los archivos que no hayan sido accedidos en 20 segundos y solo archivos que tengan al menos 5 accesos durante este tiempo. Si no va a implementar con frecuencia puede subir estos valores sin problemas.
Extracto del archivo: /etc/nginx/nginx.conf
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 5;
open_file_cache_errors off;
También puede almacenar en caché a través de una ubicación particular. Almacenar archivos en caché por un largo tiempo es beneficioso, especialmente si los archivos tiene un sistema de control de versiones entregado por el proceso de generación o el CMS.
Extracto /etc/nginx/nginx.conf
location ~* .(woff|eot|ttf|svg|mp4|webm|jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
Comprimir contenido con gzip
Para el contenido que es texto plano, Nginx puede usar la compresión gzip para volver a entregar estos recursos al cliente, pero compresos. Los navegadores web modernos aceptarán compresiones gzip y esto recortará varios bytes en cada solicitud que venga en forma de recursos en texto plano. La lista a continuación es una lista "segura" de tipos de contenido comprimible; sin embargo, solo debe habilitar los tipos de contenido que esté utilizando dentro de su aplicación web.
Extracto del archivo: /etc/nginx/nginx.conf
gzip on;
gzip_min_length 1000;
gzip_types: text/html application/x-javascript text/css application/javascript text/javascript text/plain text/xml application/json application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/xml font/eot font/opentype font/otf image/svg+xml image/vnd.microsoft.icon;
gzip_disable "MSIE [1-6]\.";
Optimizaciones del sistema de archivos
Estas operaciones en el filesystem mejorar la administración de memoria del sistema y pueden ser añadidas en el archivo /etc/sysctl.conf
.
Puertos efímeros
Cuando Nginx actúa como proxy, cada conexión en un servidor de upstream usa un puerto temporal —o efímero.
El rango de puertos locales IPv4 define un valor para el rango de puertos. Una configuración común es: net.ipv4.ip_local_port_range 1024 65000
.
El timeout de TCP FIN asegura la cantidad de tiempo en el cual un puerto debe estar inactivo antes de ser reutilizado para otra conexión. El valor predeterminado suele ser 60 segundos, pero puede ser reducido a 30 o 15 segundos en la mayoría de los casos:
Extracto del archivo: /etc/sysctl.conf
net.ipv4.tcp_fin_timeout 15
Escalamiento de la ventana TCP
La opción The TCP window
es una opción para aumentar el tamaño de la ventana de recepción permitida en el protocolo de control de transmisión o TCP por encima de su antiguo valor de 65.535 bytes. Esta opción TCP, junto con algunas otras, está definida en la hoja de especificaciones IETF RFC 1323, la cual se ocupa de grandes redes. Este valor puede ser definido con la etiqueta: net.ipv4.tcp_window_scaling = 1
.
Reservar paquetes antes de eliminarlos
El parámetro net.ipv4.tcp_max_syn_backlog
determina un número de paquetes a mantener en el backlog antes de que el kernel comience a descartarlos. Un buen valor sería: net.ipv4.tcp_max_syn_backlog = 3240000
.
Cerrar conexión tras la falta de respuesta del cliente
reset_timedout_connection on;
permite que el servidor cierre una conexión después de que un cliente deja de responder. Esto libera la memoria asociada al socket.
Descriptores de archivo
Los descriptores de archivo son recursos del sistema operativo que se usan para manejar cosas como las conexiones y abrir archivos. Nginx puede usar hasta dos descriptores de archivo por conexión. Por ejemplo, si está usado como proxy, hay generalmente un descriptor de archivo por conexión de cliente y otro para la conexión del servidor proxy, aunque esta tasa es mucho más baja si se usan keep alives de HTTP. Para un sistema que sirva a un gran número de conexiones, es probable que sea necesario cambiar esta configuración.
sys.fs.file_max
define el límite máximo de descriptores de archivo en el sistema. nofile
define el límite de descriptores de archivo para el usuario. Ambos valores se establecen en el archivo /etc/security/limits.conf
.
Extracto del archivo: /etc/security/limits.conf **
soft nofile 4096
hard nofile 4096
Registro de errores
El parámetro error_log logs/error.log warn
define la ubicación y los distintos niveles de severidad escritos en el archivo de registro o log de error. El valor definido para el nivel de log regirá los niveles de registro de errores en este archivo: se registrarán desde el nivel descrito y todos los superiores. Por ejemplo: el nivel default
de error causará que se registren los mensajes con niveles de severidad: error
, crit
, alert
y emerg
. Si este parámetro es omitido, entonces se usará error
por defecto. Los niveles se enumeran a continuación:
emerg
: las situaciones de emergencia donde el sistema está en un estado no utilizable.alert
: situaciones graves donde se requiere acción inmediata.crit
: problemas importantes que deben ser abordados.error
: un error ha ocurrido. Algo no se pudo completar con éxito.warn
: ocurrió algo fuera de lo común, pero no debe causar demasiada preocupación.notice
: Ha ocurrido algo normal, pero que vale la pena notar.info
: un mensaje de información que podría ser útil.debug
: información de depuración que puede ser útil para identificar dónde se está produciendo el problema.
Acceda a los logs con la directiva log_format
para configurar el formato de los mensajes registrados, así como con la directiva access_log
para especificar la ubicación del log y su formato.
Extracto del archivo: /etc/nginx/nginx.conf
http {
log_format compression '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" "$gzip_ratio"';
server {
gzip on;
access_log /spool/logs/nginx-access.log compression;
}
}
Registro condicional de eventos
Los logs condicionales pueden ser completados si el administrador del sistema solo quiere registrar ciertas solicitudes. El ejemplo a continuación excluye el registro de eventos para los códios estatus 2XX y 3XX en HTTP:
Extracto del archivo: /etc/nginx/nginx.conf
map $status $loggable {
~^[23] 0;
default 1;
}
Desactivar el registro de logs completamente
El registro de logs puede ser desactivado completamente si tiene una metodología de logs alternativa o si no le importa tener algún registro de eventos en su servidor. Desactivar el registro de eventos puede ser llevado a cabo con las siguientes directivas en el servidor:
Extracto del archivo: /etc/nginx/nginx.conf
server {
listen 80;
server_name example.com;
access_log off;
error_log off;
}
Supervisión de actividades
También se puede establecer la supervisión de actividades para ver respuestas JSON en tiempo real. Con la siguiente configuración, la página web status.html
ubicada en /usr/share/nginx/html
puede ser solicitada a través de la URL: http://127.0.0.1/status.html
.
Archivos de ejemplo
Después de hacer los ajustes sugeridos tendremos tres archivos para mejorar el desempeño de Nginx en su sistema. A continuación se muestran fragmentos completos a continuación.
sysctl.conf
Extracto del archivo: /etc/sysctl.conf
net.core.somaxconn = 65536
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_max_syn_backlog = 3240000
limits.conf
Extracto del archivo: /etc/security/limits.conf
soft nofile 4096
hard nofile 4096
nginx.conf
Extracto del archivo: nginx.conf
pid /var/run/nginx.pid;
worker_processes 2;
events {
worker_connections 65536;
use epoll;
multi_accept on;
}
http {
keepalive_timeout 65;
keepalive_requests 100000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
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;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 5;
open_file_cache_errors off;
gzip on;
gzip_min_length 1000;
gzip_buffers 4 4k;
gzip_types text/html application/x-javascript text/css application/javascript text/javascript text/plain text/xml application/json application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/xml font/eot font/opentype font/otf image/svg+xml image/vnd.microsoft.icon;
gzip_disable "MSIE [1-6]\.";
# [ debug | info | notice | warn | error | crit | alert | emerg ]
error_log /var/log/nginx.error_log warn;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
log_format download '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_range" "$sent_http_content_range"';
map $status $loggable {
~^[23] 0;
default 1;
}
server {
listen 127.0.0.1;
server_name 127.0.0.1;
root /var/www/html;
access_log /var/log/nginx.access_log main;
location / {
proxy_pass http://127.0.0.1/;
proxy_redirect off;
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_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_temp_path /etc/nginx/proxy_temp;
}
location ~* .(woff|eot|ttf|svg|mp4|webm|jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
}
}
Recursos adicionales
Puede consultar los siguientes recursos en busca de información adicional con respecto a este tema. Aunque este material es provisto esperando que sea útil, tenga en cuenta que no podemos dar fe de la actualidad o precisión de los contenidos externos.