BLOG | NGINX

Una guía para el almacenamiento en caché con NGINX y NGINX Plus

NGINX - Parte de F5 - horizontal, negro, tipo RGB
Miniatura de Faisal Memon
Faisal Memon
Publicado el 23 de julio de 2015

Todos sabemos que el rendimiento de las aplicações y los sitios web es un factor crítico para su éxito. Sin embargo, el proceso para lograr que su aplicação o sitio web funcione mejor no siempre es claro. La calidad del código y la infraestructura son, por supuesto, fundamentales, pero en muchos casos es posible realizar mejoras importantes en la experiencia del usuario final de su aplicação concentrándose en algunas técnicas de distribución de aplicação muy básicas. Un ejemplo de ello es la implementación y optimización del almacenamiento en caché en la pila de aplicação . Esta publicación de blog cubre técnicas que pueden ayudar tanto a los usuarios principiantes como a los avanzados a obtener un mejor rendimiento al utilizar las funciones de caché de contenido incluidas en NGINX y NGINX Plus.

INFORMACIÓN GENERAL

Un caché de contenido se ubica entre un cliente y un “servidor de origen”, y guarda copias de todo el contenido que ve. Si un cliente solicita contenido que la caché tiene almacenado, devuelve el contenido directamente sin contactar al servidor de origen. Esto mejora el rendimiento ya que el caché de contenido está más cerca del cliente y utiliza los servidores de aplicação de forma más eficiente porque no tienen que hacer el trabajo de generar páginas desde cero cada vez.

Potencialmente, existen múltiples cachés entre el navegador web y el servidor de aplicação : el caché del navegador del cliente, los cachés intermedios, las redes de distribución de contenido (CDN) y el balanceador de carga o proxy inverso ubicado frente a los servidores de aplicação . El almacenamiento en caché, incluso en el nivel de balanceador de carga/proxy inverso, puede mejorar enormemente el rendimiento.

Por ejemplo, el año pasado asumí la tarea de optimizar el rendimiento de un sitio web que se cargaba lentamente. Una de las primeras cosas que noté fue que tardaba más de 1 segundo generar la página de inicio principal. Después de depurar un poco, descubrí que, debido a que la página estaba marcada como no almacenable en caché, se generaba dinámicamente en respuesta a cada solicitud. La página en sí no cambiaba muy a menudo y no estaba personalizada, por lo que esto no era necesario. A modo de experimento, marqué la página de inicio para que el balanceador de carga la almacenara en caché durante 5 segundos y solo hacer eso resultó en una mejora notable. El tiempo hasta el primer byte se redujo a unos pocos milisegundos y la página se cargó visiblemente más rápido.

NGINX se implementa comúnmente como un proxy inverso o un balanceador de carga en una pila de aplicação y tiene un conjunto completo de funciones de almacenamiento en caché. La siguiente sección analiza cómo configurar el almacenamiento en caché básico con NGINX.

Cómo configurar el almacenamiento en caché básico

Solo se necesitan dos directivas para habilitar el almacenamiento en caché básico: proxy_cache_path y proxy_cache . La directiva proxy_cache_path establece la ruta y la configuración del caché, y la directiva proxy_cache la activa.

proxy_cache_path /ruta/a/caché niveles=1:2 zona_de_claves=mi_caché:10m tamaño_máximo=10g inactivo=60m ruta_temperatorial_de_uso=desactivado; servidor { # ... ubicación / { proxy_cache mi_caché; contraseña_de_proxy http://mi_flujo_upstream; } }

Los parámetros de la directiva proxy_cache_path definen las siguientes configuraciones:

  • El directorio del disco local para el caché se llama /ruta/al/caché/ .
  • niveles establece una jerarquía de directorios de dos niveles bajo /ruta/a/caché/ . Tener una gran cantidad de archivos en un solo directorio puede ralentizar el acceso a los archivos, por eso recomendamos una jerarquía de directorios de dos niveles para la mayoría de las implementaciones. Si no se incluye el parámetro niveles , NGINX coloca todos los archivos en el mismo directorio.
  • keys_zone configura una zona de memoria compartida para almacenar las claves de caché y metadatos, como temporizadores de uso. Tener una copia de las claves en la memoria permite a NGINX determinar rápidamente si una solicitud es un HIT o un MISS sin tener que ir al disco, lo que acelera enormemente la verificación. Una zona de 1 MB puede almacenar datos para aproximadamente 8000 claves, por lo que la zona de 10 MB configurada en el ejemplo puede almacenar datos para aproximadamente 80 000 claves.
  • max_size establece el límite superior del tamaño de la caché (a 10 gigabytes en este ejemplo). Es opcional; no especificar un valor permite que la memoria caché crezca para utilizar todo el espacio de disco disponible. Cuando el tamaño de la caché alcanza el límite, un proceso llamado administrador de caché elimina los archivos que se usaron menos recientemente para que el tamaño de la caché vuelva a estar por debajo del límite.
  • inactivo especifica cuánto tiempo puede permanecer un elemento en la memoria caché sin ser accedido. En este ejemplo, el proceso del administrador de caché elimina automáticamente del caché un archivo que no se ha solicitado durante 60 minutos, independientemente de si ha expirado o no. El valor predeterminado es 10 minutos ( 10m ). El contenido inactivo se diferencia del contenido vencido. NGINX no elimina automáticamente el contenido que ha expirado según lo definido por un encabezado de control de caché ( Cache-Control:max-age=120 por ejemplo). El contenido caducado (obsoleto) se elimina solo cuando no se ha accedido a él durante el tiempo especificado por inactivo . Cuando se accede a contenido caducado, NGINX lo actualiza desde el servidor de origen y restablece el temporizador inactivo .
  • NGINX primero escribe los archivos destinados al caché en un área de almacenamiento temporal, y la directiva use_temp_path=off le indica a NGINX que los escriba en los mismos directorios en los que se almacenarán en caché. Le recomendamos que establezca este parámetro en desactivado para evitar la copia innecesaria de datos entre sistemas de archivos. use_temp_path se introdujo en NGINX versión 1.7.10 y NGINX Plus R6 .

Y finalmente, la directiva proxy_cache activa el almacenamiento en caché de todo el contenido que coincide con la URL del bloque de ubicación principal (en el ejemplo, / ). También puede incluir la directiva proxy_cache en un bloque de servidor ; se aplica a todos los bloques de ubicación del servidor que no tienen su propia directiva proxy_cache .

Entrega de contenido en caché cuando el origen no funciona

Una característica poderosa del almacenamiento en caché de contenido de NGINX es que NGINX se puede configurar para entregar contenido obsoleto desde su caché cuando no puede obtener contenido nuevo de los servidores de origen. Esto puede suceder si todos los servidores de origen de un recurso almacenado en caché están inactivos o temporalmente ocupados. En lugar de transmitir el error al cliente, NGINX entrega la versión obsoleta del archivo desde su caché. Esto proporciona un nivel adicional de tolerancia a fallas para los servidores que NGINX utiliza como proxy y garantiza el tiempo de actividad en caso de fallas del servidor o picos de tráfico. Para habilitar esta funcionalidad, incluya la directiva proxy_cache_use_stale :

ubicación / { # ... proxy_cache_use_stale error tiempo de espera http_500 http_502 http_503 http_504; }

Con esta configuración de muestra, si NGINX recibe un error , un tiempo de espera o cualquiera de los errores 5xx especificados del servidor de origen y tiene una versión obsoleta del archivo solicitado en su caché, entrega el archivo obsoleto en lugar de retransmitir el error al cliente.

Ajuste de la caché y mejora del rendimiento

NGINX tiene una gran cantidad de configuraciones opcionales para ajustar el rendimiento de la caché. He aquí un ejemplo que activa algunos de ellos:

proxy_cache_path /ruta/a/caché niveles=1:2 zona_claves=mi_caché:10m tamaño_máximo=10g inactivo=60m ruta_temp_uso=desactivado; servidor { # ... ubicación / { proxy_cache mi_caché; proxy_cache_revalidate activado; proxy_cache_min_uses 3; proxy_cache_use_stale error tiempo de espera actualizando http_500 http_502 http_503 http_504; proxy_cache_background_update activado; proxy_cache_lock activado; proxy_pass http://mi_subida; } }

Estas directivas configuran el siguiente comportamiento:

  • proxy_cache_revalidate indica a NGINX que utilice solicitudes GET condicionales al actualizar el contenido de los servidores de origen. Si un cliente solicita un elemento que está almacenado en caché pero venció según lo definido por los encabezados de control de caché, NGINX incluye el campo If-Modified-Since en el encabezado de la solicitud GET que envía al servidor de origen. Esto ahorra ancho de banda, porque el servidor envía el elemento completo solo si se ha modificado desde el momento registrado en el encabezado Última modificación adjunto al archivo cuando NGINX lo almacenó en caché originalmente.
  • proxy_cache_min_uses establece la cantidad de veces que los clientes deben solicitar un elemento antes de que NGINX lo almacene en caché. Esto es útil si el caché se llena constantemente, ya que garantiza que solo los elementos a los que se accede con más frecuencia se agreguen al caché. De forma predeterminada, proxy_cache_min_uses se establece en 1.
  • El parámetro de actualización de la directiva proxy_cache_use_stale , combinado con la habilitación de la directiva proxy_cache_background_update , indica a NGINX que entregue contenido obsoleto cuando los clientes solicitan un elemento que ha vencido o está en proceso de actualización desde el servidor de origen. Todas las actualizaciones se realizarán en segundo plano. El archivo obsoleto se devuelve para todas las solicitudes hasta que el archivo actualizado se haya descargado por completo.
  • Con proxy_cache_lock habilitado, si varios clientes solicitan un archivo que no está actual en el caché (un MISS ), solo la primera de esas solicitudes puede pasar al servidor de origen. Las solicitudes restantes esperan a que se satisfaga esa solicitud y luego extraen el archivo de la memoria caché. Sin proxy_cache_lock habilitado, todas las solicitudes que resulten en errores de caché van directamente al servidor de origen.

Dividir la caché entre varios discos duros

Si tiene varios discos duros, se puede utilizar NGINX para dividir el caché entre ellos. A continuación se muestra un ejemplo que divide a los clientes de manera uniforme en dos discos duros según el URI de la solicitud:

ruta_caché_proxy /ruta/al/ddd1 niveles=1:2 zona_claves=mi_caché_ddd1:10m tamaño_máx.=10g inactivo=60m ruta_temp._uso=desactivada;
ruta_caché_proxy /ruta/al/ddd2 niveles=1:2 zona_claves=mi_caché_ddd2:10m
tamaño_máx.=10g inactivo=60m ruta_temp._uso=desactivada;

split_clients $request_uri $mi_caché {
50% “mi_caché_ddd1”;
50% “mi_caché_ddd2”;
}

servidor {
# ...
ubicación / {
caché_proxy $mi_caché;
contraseña_proxy http://mi_flujo_de_carga;
}
}

Las dos directivas proxy_cache_path definen dos cachés ( my_cache_hdd1 y my_cache_hdd2 ) en dos discos duros diferentes. El bloque de configuración split_clients especifica que los resultados de la mitad de las solicitudes ( 50% ) se almacenan en caché en my_cache_hdd1 y la otra mitad en my_cache_hdd2 . El hash basado en la variable $request_uri (el URI de la solicitud) determina qué caché se utiliza para cada solicitud, y el resultado es que las solicitudes para un URI determinado siempre se almacenan en el mismo caché.

Tenga en cuenta que este enfoque no reemplaza una configuración de disco duro RAID. Si hay una falla en el disco duro, esto podría generar un comportamiento impredecible en el sistema, incluidos usuarios que ven códigos de respuesta 500 para solicitudes dirigidas al disco duro fallado. Una configuración adecuada del disco duro RAID puede solucionar los fallos del disco duro.

Preguntas frecuentes (FAQ)

Esta sección responde algunas preguntas frecuentes sobre el almacenamiento en caché de contenido de NGINX.

¿Se puede instrumentar la caché NGINX?

Sí, con la directiva add_header :

agregar_encabezado Estado de caché X $upstream_cache_status;

Este ejemplo agrega un encabezado HTTP X-Cache-Status en las respuestas a los clientes. Los siguientes son los valores posibles para $upstream_cache_status :

  • MISS – La respuesta no se encontró en la memoria caché, por lo que se obtuvo de un servidor de origen. Es posible que la respuesta haya quedado almacenada en caché.
  • BYPASS – La respuesta se obtuvo del servidor de origen en lugar de servirse desde el caché porque la solicitud coincidía con una directiva proxy_cache_bypass (consulte ¿Puedo hacer un agujero en mi caché? a continuación). Es posible que la respuesta haya quedado almacenada en caché.
  • CADUCADO – La entrada en la caché ha expirado. La respuesta contiene contenido nuevo del servidor de origen.
  • OBSOLETO : el contenido está obsoleto porque el servidor de origen no responde correctamente y se configuró proxy_cache_use_stale .
  • ACTUALIZACIÓN : El contenido está desactualizado porque la entrada se está actualizando actualmente en respuesta a una solicitud anterior y la actualización proxy_cache_use_stale está configurada.
  • REVALIDADO – Se habilitó la directiva proxy_cache_revalidate y NGINX verificó que el contenido almacenado en caché actual aún era válido ( If-Modified-Since o If-None-Match ).
  • HIT – La respuesta contiene contenido válido y nuevo directamente desde el caché.

¿Cómo determina NGINX si debe almacenar algo en caché o no?

NGINX almacena en caché una respuesta solo si el servidor de origen incluye el encabezado Expires con una fecha y hora en el futuro, o el encabezado Cache-Control con la directiva max-age establecida en un valor distinto de cero.

De forma predeterminada, NGINX respeta otras directivas en el encabezado Cache-Control : no almacena en caché las respuestas cuando el encabezado incluye la directiva Private , No-Cache o No-Store . Tampoco almacena en caché las respuestas con el encabezado Set-Cookie . Además, solo almacena en caché las respuestas a las solicitudes GET y HEAD . Puede anular estos valores predeterminados como se describe en las respuestas a continuación.

NGINX no almacena en caché las respuestas si proxy_buffering está desactivado . Está activado de forma predeterminada.

¿Es posible ignorar los encabezados de control de caché ?

Sí, con la directiva proxy_ignore_headers . Por ejemplo, con esta configuración:

ubicación /imágenes/ { proxy_cache mi_cache; proxy_ignorar_encabezados Control de caché; proxy_cache_válido cualquier 30m; # ... }

NGINX ignora el encabezado Cache-Control para todo lo que se encuentra bajo /images/ . La directiva proxy_cache_valid impone una expiración para los datos almacenados en caché y es necesaria si se ignoran los encabezados Cache-Control . NGINX no almacena en caché archivos que no tienen fecha de caducidad.

¿Puede NGINX almacenar en caché contenido con una cookie establecida en el encabezado?

Sí, con la directiva proxy_ignore_headers , como se discutió en la respuesta anterior.

¿Puede NGINX almacenar en caché solicitudes POST ?

Sí, con la directiva proxy_cache_methods :

métodos de caché proxy OBTENER PUBLICACIÓN PRINCIPAL;

Este ejemplo habilita el almacenamiento en caché de solicitudes POST .

¿Puede NGINX almacenar en caché contenido dinámico?

Sí, siempre que el encabezado Cache-Control lo permita. El almacenamiento en caché de contenido dinámico incluso durante un período corto de tiempo puede reducir la carga en los servidores de origen y las bases de datos, lo que mejora el tiempo hasta el primer byte, ya que no es necesario regenerar la página para cada solicitud.

¿Puedo hacer un agujero en mi caché?

Sí, con la directiva proxy_cache_bypass :

ubicación / { proxy_cache_bypass $cookie_nocache $arg_nocache; # ... }

La directiva define los tipos de solicitud para los cuales NGINX solicita contenido del servidor de origen inmediatamente en lugar de intentar encontrarlo primero en el caché. A esto a veces se le llama “hacer un agujero” en el caché. En este ejemplo, NGINX lo hace para solicitudes con una cookie o argumento no cache , por ejemplo http://www.example.com/?nocache=true . NGINX aún puede almacenar en caché la respuesta resultante para futuras solicitudes que no se omitan.

¿Qué clave de caché utiliza NGINX?

La forma predeterminada de las claves que genera NGINX es similar a un hash MD5 de las siguientes variables NGINX : $scheme$proxy_host$request_uri ; el algoritmo real utilizado es ligeramente más complicado.

ruta_caché_proxy /ruta/a/caché niveles=1:2 zona_claves=mi_caché:10m tamaño_máximo=10g inactivo=60m ruta_temp_uso=desactivado;

servidor {
# ...
ubicación / {
caché_proxy mi_caché;
contraseña_proxy http://mi_flujo_de_subida;
}
}

Para esta configuración de muestra, la clave de caché para http://www.example.org/my_image.jpg se calcula como md5(“http://my_upstream:80/my_image.jpg”) .

Tenga en cuenta que la variable $proxy_host se utiliza en el valor hash en lugar del nombre de host real ( www.example.com ). $proxy_host se define como el nombre y el puerto del servidor proxy como se especifica en la directiva proxy_pass .

Para cambiar las variables (u otros términos) utilizadas como base de la clave, utilice la directiva proxy_cache_key (consulte también la siguiente pregunta).

¿Puedo utilizar una cookie como parte de mi clave de caché?

Sí, la clave de caché se puede configurar para que sea cualquier valor arbitrario, por ejemplo:

clave_caché_proxy $host_proxy$uri_solicitud$id_cesión_de_cookie;

Este ejemplo incorpora el valor de la cookie JSESSIONID en la clave de caché. Los elementos con el mismo URI pero diferentes valores JSESSIONID se almacenan en caché por separado como elementos únicos.

¿NGINX utiliza el encabezado ETag ?

En NGINX 1.7.3 y NGINX Plus R5 y posteriores, el encabezado ETag es totalmente compatible junto con If-None-Match .

¿Cómo maneja NGINX las solicitudes de rango de bytes?

Si el archivo está actualizado en la memoria caché, entonces NGINX respeta una solicitud de rango de bytes y entrega solo los bytes especificados del elemento al cliente. Si el archivo no está almacenado en caché o está desactualizado, NGINX descarga el archivo completo desde el servidor de origen. Si la solicitud es para un solo rango de bytes, NGINX envía ese rango al cliente tan pronto como lo encuentra en el flujo de descarga. Si la solicitud especifica múltiples rangos de bytes dentro del mismo archivo, NGINX entrega el archivo completo al cliente cuando se completa la descarga.

Una vez que se completa la descarga, NGINX mueve todo el recurso a la memoria caché para que todas las futuras solicitudes de rango de bytes, ya sea para un solo rango o para varios rangos, se satisfagan inmediatamente desde la memoria caché.

Tenga en cuenta que el servidor ascendente debe admitir solicitudes de rango de bytes para que NGINX respete las solicitudes de rango de bytes a ese servidor ascendente .

¿NGINX admite la purga de caché?

NGINX Plus admite la purga selectiva de archivos almacenados en caché. Esto es útil si un archivo se ha actualizado en el servidor de origen pero aún es válido en el caché de NGINX Plus ( Cache-Control:max-age aún es válido y el tiempo de espera establecido por el parámetro inactivo en la directiva proxy_cache_path no ha expirado). Con la función de purga de caché de NGINX Plus, este archivo se puede eliminar fácilmente. Para obtener más detalles, consulte Purgar contenido de la caché .

¿Cómo maneja NGINX el encabezado Pragma ?

Los clientes agregan el encabezado Pragma:no-cache para omitir todos los cachés intermedios e ir directamente al servidor de origen para obtener el contenido solicitado. NGINX no respeta el encabezado Pragma de forma predeterminada, pero puedes configurar la función con la siguiente directiva proxy_cache_bypass :

ubicación /imágenes/ { proxy_cache mi_cache; proxy_cache_bypass $http_pragma; # ... }

¿NGINX admite las extensiones stale-while-revalidate y stale-if-error en el encabezado Cache-Control ?

Sí, en NGINX Plus R12 y NGINX 1.11.10 y posteriores. Qué hacen estas extensiones:

  • La extensión stale-while-revalidate del encabezado HTTP Cache-Control permite utilizar una respuesta en caché obsoleta si actualmente se está actualizando.
  • La extensión stale-if-error del encabezado HTTP Cache-Control permite utilizar una respuesta en caché obsoleta en caso de un error.

Estos encabezados tienen una prioridad menor que la directiva proxy_cache_use_stale descrita anteriormente.

¿NGINX admite el encabezado Vary ?

Sí, en NGINX Plus R5 y NGINX 1.7.7 y posteriores. Aquí hay una buena descripción general del encabezado Vary .

Más información

Hay muchas más formas de personalizar y ajustar el almacenamiento en caché de NGINX. Para obtener más información sobre el almacenamiento en caché con NGINX, consulte los siguientes recursos:


"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.