
Esta entrada es una adaptación de un seminario web de Owen Garrett, presentado por Andrew Alexeev.
Índice
Introducción
0:00 Introducción1:22 Acerca de este seminario web2:17 Principios básicos del almacenamiento en caché de contenido2:35 Principios básicos3:59 Funcionamiento del almacenamiento en caché HTTP7:46 ¿Qué almacena NGINX en caché?
Almacenamiento en caché de contenido y NGINX
9:55 NGINX en funcionamiento10:06 Configuración de NGINX11:14 Proceso de almacenamiento en caché15:32 El almacenamiento en caché no es solo para HTTP17:10 Cómo entender lo que está ocurriendo17:38 Instrumentación de la caché19:08 Instrumentación de la caché (cont.)20:09 Estado de la caché21:57 Cómo funciona el almacenamiento de contenido en caché en NGINX22:40 Cómo funciona23:53 ¿Cómo se almacena el contenido en caché?26:36 Carga de la caché desde el disco28:07 Gestión de la caché en disco29:22 Eliminación del contenido del disco
Control del almacenamiento en caché
31:27 Control del almacenamiento en caché32:30 Almacenamiento en caché diferido34:45 Control del tiempo de almacenamiento en caché36:18 Almacenar / No almacenar en caché37:25 Varias cachés39:07 Repaso rápido – ¿Por qué usar la caché?39:44 ¿Por qué es importante la velocidad de la página?40:46 Google cambió las reglas41:28 Los costes de un rendimiento deficiente43:00 El almacenamiento en caché de NGINX permite45:21 Reflexiones finales
Preguntas y respuestas
47:20 Solicitudes de intervalos de bytes49:13 Revalidación de la caché del proxy50:07 Distribución de la caché entre discos de igual capacidad50:50 Vary Cabecera51:25 Primitivas de almacenamiento en caché51:52 Cabeceras y datos del servidor de origen52:13 *‑Encoding Cabeceras52:56 SPDY53:15 Vary Cabecera, segunda parte53:45 PageSpeed54:00 Otras cachés
0:00 Introducción

Andrew Alexeev: Bienvenidos a nuestro último seminario web; me llamo Andrew. NGINX fue creado por Igor Sysoev con el objetivo de ayudar a que los sitios web de todo el mundo funcionaran más rápido, respondieran mejor y pudieran escalar fácilmente. Actualmente, NGINX está presente en más del 30 % de los sitios web más importantes y en más del 20 % de todos los sitios web de Internet. [Nota del editor: Estas estadísticas correspondían al momento en que se impartió el seminario web, en mayo de 2014; consulte los valores actuales aquí.] Espero que el contenido de este seminario web les resulte útil y aplicable a su entorno NGINX actual o previsto.
Ahora permítanme presentarles a Owen Garrett. Owen es el responsable del desarrollo de productos aquí en NGINX. Hoy, Owen va a explicar cómo pueden aplicar los potentes mecanismos de almacenamiento en caché de NGINX para liberar a su aplicación de la carga de generar el mismo contenido una y otra vez.
1:22 Acerca de este seminario web

Owen Garrett: Gracias, Andrew, y muchas gracias a todos por acompañarnos durante los próximos 45 o 50 minutos. Explicaré cómo funciona NGINX en lo que respecta al almacenamiento en caché de contenido, veremos algunas formas de mejorar el rendimiento, profundizaremos un poco en cómo funciona realmente el almacenamiento en caché de contenido para que podáis depurar y diagnosticar lo que ocurre dentro de NGINX, y terminaré con algunos trucos y consejos ingeniosos que os permitirán controlar con gran precisión lo que hace NGINX con el contenido que se puede almacenar en caché.
Todo ello con los mismos objetivos fundamentales que describió Andrew: liberar a los servidores de origen de la carga que supone generar contenido repetitivo, para que puedan ejecutar las aplicaciones que su empresa realmente necesita. Ir más allá de esos servidores para ofrecer a los usuarios finales un mejor nivel de servicio y aumentar la fiabilidad del servicio en su conjunto ante grandes picos de tráfico procedente de Internet y, potencialmente, fallos de los servidores de origen.
2:17 Principios básicos del almacenamiento en caché de contenidos

Antes de entrar en la configuración de la implementación de NGINX, me gustaría repasar brevemente cómo funciona el almacenamiento en caché de contenidos, para que todos partamos de la misma base y compartamos la misma información fundamental.
2:35 Principios básicos

El principio básico del almacenamiento en caché de contenido consiste en descargar a los servidores de origen del trabajo repetitivo. Cuando el primer usuario solicita un elemento de contenido del sitio web (representado por el icono y las líneas azules), su solicitud HTTP se reenvía a NGINX y, desde allí, al servidor de origen de color gris situado a la derecha.
La respuesta se reenvía al usuario remoto, pero, si se puede almacenar en caché (enseguida explicaremos qué significa esto), NGINX guarda una copia de dicha respuesta. Cuando otro usuario, el de color naranja, solicita el mismo contenido, NGINX puede proporcionárselo directamente desde su caché local en lugar de enviar la solicitud al servidor de origen.
Este principio básico de almacenar contenido invariable que se puede guardar en caché lo utilizan su navegador web, las CDN —que aprovechan los sitios web a los que accede— y NGINX en otros dispositivos. Funciona como una caché de proxy inverso, que normalmente se implementa en el centro de datos o en la nube, junto a los servidores de origen que alojan su contenido web y sus aplicaciones web.
3:59 Mecánica del almacenamiento en caché HTTP

El servidor de origen declara si el contenido se puede almacenar en caché mediante una o varias cabeceras de respuesta HTTP conocidas y ampliamente comprendidas. Por supuesto, los servidores de caché pueden optar por ignorar, anular o modificar este comportamiento. Sin embargo, para comprender la configuración del almacenamiento de contenido en caché, primero hay que entender bien cómo indica un servidor de origen que el contenido se puede almacenar en caché, que no cambia y que la copia [almacenada en caché] tiene una vida útil determinada.
El almacenamiento en caché de contenido comenzó con una sencilla cabecera de respuesta HTTP denominada Expires. El servidor de origen proporcionaba contenido y declaraba que este sería válido hasta la fecha indicada en la cabecera Expires. Este método fue rápidamente sustituido por otro más eficaz y flexible: la cabecera Cache-Control.
Expires resulta algo engorroso de usar y es poco eficiente. Las fechas deben tener el formato correcto y analizarse, mientras que Cache-Control es mucho más sencillo y se adapta mejor a las necesidades y la velocidad de las cachés de contenido. Cache-Control declara el contenido como público o privado y, si es público, especifica un valor de max-age —el número de segundos durante los que puede almacenarse en caché antes de que el sistema de caché tenga que volver a solicitarlo.
La tercera cabecera que controla directamente el almacenamiento en caché es X-Accel-Expires. Esta cabecera es específica de NGINX; solo NGINX la interpreta y se utiliza cuando se desea anular el comportamiento de las cabeceras anteriores e indicar directamente a NGINX durante cuánto tiempo debe almacenarse en caché un elemento de contenido.
Hay situaciones en las que puede interesarle que el navegador web almacene el contenido en caché durante un periodo prolongado, pero que la caché del proxy (NGINX situado delante del servidor de origen) lo almacene durante menos tiempo, de modo que los cambios se reflejen más rápidamente y se distribuyan a los nuevos clientes, mientras que los clientes antiguos no vuelvan a solicitar el contenido cuando no sea necesario.
Sin embargo, ese método también se puede implementar mediante las dos últimas cabeceras. Un servidor de origen puede indicar cuándo se modificó por última vez un elemento de contenido y puede declarar algo denominado ETag (etiqueta de entidad), una cadena opaca, a menudo un valor hash, que identifica dicho contenido.
A continuación, los clientes pueden realizar solicitudes mediante GET condicionales. Pueden incluir una cabecera If-Modified-Since o If-None-Match en su solicitud. De este modo, el cliente indica que tiene una versión del contenido en caché que se modificó por última vez en una fecha determinada o que tiene un ETag concreto. Si la versión más reciente que tiene el servidor coincide con la que tiene el cliente, el servidor responde simplemente con un 304 Not Modified. Esta respuesta es rápida, ahorra ancho de banda de red y permite al cliente comprobar cuando lo desee si la copia del contenido almacenada en caché sigue siendo válida.
Estas cinco cabeceras definen, desde la perspectiva de un servidor de origen, cómo se puede almacenar en caché el contenido: su validez, su frescura y, en lo que respecta al ETag, los detalles del propio contenido.
7:46 ¿Qué almacena NGINX en caché?

Las cachés proxy como NGINX tienen bastante libertad para interpretar hasta qué punto deben respetar esas cabeceras. Evidentemente, no deberían almacenar en caché algo que no se pueda almacenar, pero, por supuesto, tampoco tienen la obligación de hacerlo si el servidor de origen indica que sí se puede.
El comportamiento básico de NGINX consiste en almacenar en caché todas las solicitudes GET y HEAD que el servidor de origen indique que se pueden almacenar en caché, siempre que no haya encabezados Set-Cookie en la respuesta. Esto se debe a que los encabezados Set-Cookie suelen incluir datos únicos específicos de cada solicitud y, de forma predeterminada, no sería apropiado almacenar ese valor en caché.
NGINX almacena en caché cada recurso mediante una clave específica: una clave de caché. Todas las solicitudes que generen la misma clave de caché recibirán el mismo recurso. De forma predeterminada, la caché se corresponde con la URL sin procesar o, en la configuración, con la cadena que se muestra en esta diapositiva [$scheme$proxy_host$uri$is_args$args]. Cuando NGINX almacena contenido en caché, [el periodo de validez] se define (por orden de prioridad) mediante la cabecera X-Accel-Expires, si está presente, o mediante la cabecera Cache-Control o la cabecera heredada Expires.
Puede configurar NGINX para que omita algunas de estas cabeceras o establezca un tiempo de almacenamiento en caché fijo, independientemente de lo que indique el servidor de origen. Como referencia, RFC 2616 define el comportamiento esperado de una caché proxy con respecto a HTTP.
Esto le ofrece una breve idea de la universalidad del almacenamiento en caché y del comportamiento predeterminado básico de NGINX al almacenar en caché contenido que normalmente se puede guardar de forma segura, con el fin de acelerar su sitio web y reducir la carga de sus servidores de origen.
9:55 NGINX en funcionamiento

Ahora veamos brevemente NGINX en funcionamiento. Configurar NGINX para habilitar el almacenamiento en caché de contenido es realmente muy fácil.
10:06 Configuración de NGINX

Son un par de líneas en el archivo de configuración de NGINX: una para crear una caché en disco con una serie de parámetros que especifican cómo se organizan los archivos, el tiempo de caducidad [de los objetos de esa caché] y el tamaño de la caché. La segunda, la directiva proxy_cache, está asociada a un proxy de NGINX y le indica que el contenido (resultados, respuestas) debe almacenarse en una caché con nombre.
Así que aquí he creado una caché llamada «one»; tiene un tamaño de 10 MB en memoria para los metadatos, pero no tiene límite de tamaño en disco para el contenido almacenado en caché. El contenido se almacena en caché y se elimina si permanece inactivo durante 60 minutos. Nuestro servidor predeterminado utiliza esa caché llamada «one». Estas dos [directivas], proxy_cache_path y proxy_cache, bastan para habilitar un almacenamiento en caché fiable y coherente para un servidor proxy en NGINX.
11:14 Proceso de almacenamiento en caché

El proceso que sigue NGINX cuando recibe una solicitud y consulta una caché se define de la siguiente manera. Comenzamos leyendo una solicitud (recuadro superior izquierdo de esta diapositiva) y creando la clave de caché a partir del URI sin procesar y de los demás parámetros que vamos a utilizar para identificar el recurso correspondiente a dicha solicitud. A continuación, comprobamos la caché en disco accediendo a los metadatos almacenados en memoria para determinar si disponemos de una copia válida y actualizada de la respuesta a esa solicitud.
Si la tenemos, se considera un acierto. En ese caso, NGINX puede responder directamente desde la caché. Para ello, sirve el contenido desde el disco exactamente igual que sirve el contenido estático. De este modo, se obtiene el nivel de rendimiento, fiabilidad y escalabilidad para el que se ha diseñado NGINX. Al servir contenido desde la caché de contenido de NGINX, se obtiene exactamente el mismo nivel [de rendimiento] que con el contenido estático.
Por otro lado, cuando comprobamos la caché, puede producirse un fallo de caché. Esto significa que el contenido no está en la caché o que el contenido almacenado está desactualizado y debe actualizarse. En el caso más sencillo, ese fallo implica que solicitamos el contenido al servidor de origen, recibimos la respuesta y comprobamos si se puede almacenar en caché.
Si lo es, lo transmitimos al disco, tal como hace NGINX con cualquier respuesta de gran tamaño gestionada en modo proxy. Una vez que [la respuesta] se ha transmitido al disco, la copiamos en la caché y respondemos directamente desde ella. Uno de los problemas de este enfoque surge cuando NGINX recibe varias solicitudes simultáneas del mismo contenido y todas provocan un fallo de caché.
Normalmente, NGINX reenviaría todas esas solicitudes al servidor de origen, lo que podría sobrecargarlo, especialmente en el caso de solicitudes cuyas respuestas tardan mucho tiempo en generarse. Por ese motivo, puede utilizar un bloqueo de caché. La directiva «proxy_cache_lock» garantiza que, si se está actualizando un contenido, solo se envíe una solicitud cada vez al servidor ascendente.
Así pues, en el escenario que he descrito, la primera solicitud se enviaría al servidor ascendente, pero las demás solicitudes del mismo contenido quedarían retenidas hasta que la respuesta se haya servido y almacenado en la caché (momento en el que se podrán atender todas las solicitudes), o hasta que se alcance el tiempo de espera [establecido mediante la directiva proxy_cache_lock_timeout] – NGINX ha esperado el tiempo suficiente para que el servidor devuelva el contenido y, en ese momento, las solicitudes retenidas se reenvían al servidor de origen.
Así, proxy_cache_lock y el tiempo de espera le ofrecen un potente mecanismo de control para garantizar que, cuando tenga un sitio con mucho tráfico y numerosas solicitudes del mismo contenido, si dicho contenido caduca en la caché, no sobrecargue de repente el servidor de origen con múltiples solicitudes.
Hay un elemento más en el proceso de almacenamiento en caché de NGINX que no encaja del todo en este diagrama de flujo, ya que abarca casi todas sus etapas. Se trata de la funcionalidad configurada mediante la directiva proxy_cache_use_stale. Si en algún momento una de estas etapas falla por algún motivo —por ejemplo, si al actualizar el contenido se agota el tiempo de espera, recibimos una respuesta incorrecta del servidor de origen o se produce algún otro tipo de error—, podemos responder directamente desde la caché aunque el contenido almacenado esté obsoleto.
Esta es una herramienta realmente potente para cuando los servidores de origen están saturados por el tráfico o fallan debido a tareas de mantenimiento o a un error catastrófico. Garantiza que NGINX pueda seguir sirviendo el contenido utilizando el contenido obsoleto de la caché, en lugar de devolver un mensaje de error al cliente.
15:32 El almacenamiento en caché no es solo para HTTP

El almacenamiento en caché de NGINX no se limita a HTTP. NGINX es mucho más que un simple proxy HTTP que reenvía solicitudes a servidores web ascendentes. Por lo general, esos servidores web ascendentes se encargan de interactuar con API como FastCGI o SCGI. NGINX puede hacerlo directamente actuando como proxy, de forma muy similar al proxy HTTP.
NGINX puede emplear sus técnicas de almacenamiento en caché para proxies HTTP, para proxies FastCGI, para proxies uWSGI y para proxies SCGI. Todos funcionan de forma muy similar al proxy HTTP, con las cachés almacenadas en disco y respuestas directas, lo que evita la necesidad de reenviar las solicitudes a estos servicios ascendentes.
NGINX también puede interactuar con un servidor memcached; se trata de un enfoque de almacenamiento en caché ligeramente distinto. En este caso, NGINX no almacena el contenido directamente, sino que utiliza memcached como proxy y depende de un agente externo para cargar en memcached el contenido necesario. Esta puede ser otra herramienta útil y, si es necesario, existen muchas formas de cargar datos en memcached desde un sitio externo. Por tanto, podría considerarse una forma de precargar una caché para NGINX si así lo requieren las necesidades de su empresa.
17:10 Cómo entender qué está pasando

El almacenamiento en caché puede llegar a ser muy complejo si se dispone de una gran infraestructura con varios niveles, algunos de los cuales almacenan contenido en caché y otros no, mientras que unos generan contenido y otros no. En ese caso, puede resultar bastante difícil empezar a hacer un seguimiento de lo que ocurre —de dónde procede el contenido—, así como diagnosticar y depurar cualquier problema que surja. En NGINX, hacemos todo lo posible para que le resulte sencillo.
17:38 Instrumentación de la caché

Con algunas herramientas de instrumentación avanzadas, puede controlar dinámicamente la instrumentación para rastrear de dónde procede el contenido, dónde se almacena en la caché y cuál es su estado en ella.
El primer paso es la variable $upstream_cache_status, que se calcula para cada solicitud a la que NGINX ha respondido, independientemente de si procede de la caché o no. El valor de esa variable se añade siempre a la respuesta mediante la directiva add_header. Por convención, incluimos ese valor en una cabecera X-Cache-Status de la respuesta. Puede adoptar uno de siete valores distintos, que indican cómo se ha servido ese contenido: si se ha omitido la caché, si procede de una revalidación o si se ha encontrado en la caché.
Este es el primer paso para intentar averiguar de dónde proceden las respuestas. ¿Proceden de la caché local de NGINX o de un servidor ascendente? Puede inspeccionar esa cabecera de respuesta de varias formas: desde la línea de comandos con herramientas como curl, o bien, como suele ser habitual, desde el navegador web mediante depuradores interactivos.
Por supuesto, puede que no quiera mostrar ese valor a todos los usuarios finales. Le convendría decidir cuidadosamente cuándo incluirlo en la cabecera de respuesta.
19:08 Instrumentación de la caché (cont.)

El lenguaje de configuración de NGINX ofrece la flexibilidad necesaria para aplicar esta opción de forma selectiva. Este ejemplo muestra solo una de las muchas formas de hacerlo. Tomamos la dirección remota y, si resulta ser localhost, guardamos $upstream_cache_status en una variable temporal ($cache_status). Por último, cuando devolvemos una respuesta, incluimos la variable temporal en ella.
De este modo, solo las solicitudes procedentes de determinadas direcciones IP verán el valor de la variable $upstream_cache_status. También puede hacer muchas otras cosas; en breve veremos cómo se almacena el contenido en el disco. Puede incluir en la respuesta la clave que se utiliza para calcular la ubicación en el disco. Puede incluir todo tipo de parámetros en la respuesta para facilitar el diagnóstico de la caché mientras está en funcionamiento.
20:09 Estado de la caché

NGINX Plus, nuestra versión comercial de NGINX, ofrece una serie de funciones adicionales que resultan útiles en casos de uso como el almacenamiento en caché. NGINX Plus es una compilación de NGINX con soporte comercial, creada por nuestro equipo de ingeniería en Moscú y sometida a un amplio conjunto de pruebas de regresión para garantizar su correcto funcionamiento.
NGINX Plus también incluye una serie de funciones dirigidas a las empresas que desean utilizar NGINX como proxy inverso y equilibrador de carga. Funciones relacionadas con el equilibrio de carga, las comprobaciones de estado y la transmisión avanzada de vídeo. Y, en este contexto, funciones relacionadas con la información de estado ampliada, mejores diagnósticos y la visualización de lo que ocurre en NGINX.
[Editor – La diapositiva anterior y el párrafo siguiente se han actualizado para hacer referencia a la API de NGINX Plus, que sustituye al módulo de estado independiente mencionado originalmente aquí y lo marca como obsoleto.]
Para ver una demostración, puede acceder a demo.nginx.com/dashboard.html y verá una página web que muestra los datos de estado publicados desde NGINX Plus mediante la API de NGINX Plus. Y si ejecuta el comando curl indicado, verá los datos JSON sin procesar obtenidos directamente del binario de NGINX Plus (en este caso, se canalizan a la utilidad jq para mostrar cada elemento en una línea independiente y con sangría jerárquica).
En esos datos JSON encontrará información en tiempo real sobre el estado de cada una de las cachés de su implementación de NGINX Plus. Esto, junto con la variable $upstream_cache_status y las demás formas de monitorizar la caché, le ofrece una visión general muy completa de cómo NGINX almacena contenido en caché y le permite analizar solicitudes concretas para determinar si proceden de la caché y cuál es su estado actual en ella.
21:57 Cómo funciona el almacenamiento en caché de contenido en NGINX

Ahora que hemos visto cómo podemos examinar el almacenamiento en caché de contenido desde fuera, veámoslo desde dentro. ¿Cómo funciona en NGINX? Como he mencionado antes, la caché de contenido de NGINX funciona de forma muy similar a la gestión de los archivos en disco. Al servir contenido desde nuestra caché, se obtiene el mismo rendimiento, la misma fiabilidad y las mismas optimizaciones del sistema operativo que al servir contenido estático: el rendimiento por el que NGINX es conocido.
22:40 Cómo funciona

La caché de contenido se almacena en el disco de forma persistente. Trabajamos conjuntamente con el sistema operativo para cargar esa caché de disco en la memoria, proporcionando indicaciones a la caché de páginas del sistema operativo sobre qué contenido debe almacenarse en la memoria. Esto significa que, cuando necesitamos servir contenido desde la caché, podemos hacerlo con gran rapidez.
Los metadatos de la caché, es decir, la información sobre su contenido y su fecha de caducidad, se almacenan por separado en una sección de memoria compartida entre todos los procesos de NGINX y están siempre disponibles en memoria. De este modo, NGINX puede consultar y buscar en la caché con gran rapidez; solo necesita acceder a la caché de páginas cuando debe recuperar la respuesta y enviársela al usuario final.
Veremos cómo se almacena el contenido en la caché, cómo se carga esa caché persistente en procesos de trabajo de NGINX vacíos durante el arranque, algunas de las tareas de mantenimiento que NGINX realiza automáticamente en la caché y, para terminar, cómo se puede eliminar manualmente contenido de la caché en determinadas situaciones.
23:53 ¿Cómo se almacena el contenido en caché?

Como recordarás, la caché de contenido se declara mediante una directiva denominada proxy_cache_path. Esta directiva especifica varios parámetros: dónde se almacena la caché en el sistema de archivos, el nombre de la caché, el tamaño de la caché en memoria para los metadatos y el tamaño de la caché en disco. En este caso, hay una caché de 40 MB en disco.
La clave para entender dónde se almacena el contenido es comprender la clave de caché, es decir, el identificador único que NGINX asigna a cada recurso que se puede almacenar en caché. De forma predeterminada, ese identificador se crea a partir de los parámetros básicos de la solicitud: el esquema, la cabecera Host de la solicitud, el URI y cualquier argumento de cadena.
Pero, si lo desea, puede ampliar esa clave utilizando elementos como los valores de las cookies, las cabeceras de autenticación o incluso valores calculados en tiempo de ejecución. Por ejemplo, puede que quiera almacenar versiones diferentes para los usuarios del Reino Unido y para los de Estados Unidos. Todo esto es posible configurando la directiva proxy_cache_key.
Cuando NGINX procesa una solicitud, calcula la clave proxy_cache_key y, a partir de ese valor, calcula una suma MD5. Puedes reproducirlo usando el ejemplo de línea de comandos que aparece más abajo en la diapositiva. Tomamos la clave de caché httplocalhost:8002/time.php y la pasamos por md5sum. Cuando lo hagas desde el shell, ten cuidado de no incluir también un salto de línea.
Esto calculará el valor hash MD5 correspondiente a ese contenido almacenable en caché. NGINX utiliza dicho valor hash para determinar la ubicación del disco en la que debe almacenarse el contenido. En proxy_cache_path verá que especificamos una caché de dos niveles, con un directorio de un carácter y, a continuación, otro de dos caracteres. Tomamos esos caracteres del final de la cadena para crear un directorio llamado 4 y un subdirectorio llamado 9b, y después guardamos el contenido de la caché (junto con las cabeceras y una pequeña cantidad de metadatos) en un archivo del disco.
Puede probar el almacenamiento en caché del contenido. Puede mostrar la clave de caché como una de las cabeceras de respuesta y pasarla por md5sum para calcular el hash correspondiente a ese valor. Después, puede inspeccionar el valor en el disco para comprobar que realmente está ahí, así como las cabeceras que NGINX ha almacenado en caché, y entender cómo encaja todo.
26:36 Carga de la caché desde el disco

Ahora que el contenido se almacena en disco de forma persistente, cuando NGINX se inicia necesita cargarlo en memoria; o, más concretamente, debe recorrer la caché en disco, extraer los metadatos y cargarlos en el segmento de memoria compartida que utiliza cada uno de los procesos de trabajo. Esto se lleva a cabo mediante un proceso denominado cargador de caché.
Al iniciarse NGINX, se pone en marcha un cargador de caché que se ejecuta una sola vez y carga los metadatos del disco en pequeños lotes: 100 archivos cada vez, durante un máximo de 200 ms, con pausas de 50 ms entre cada lote. Este proceso se repite hasta recorrer toda la caché y llenar el segmento de memoria compartida.
A continuación, el cargador de caché finaliza y no necesita volver a ejecutarse, salvo que NGINX se reinicie o se reconfigure y sea necesario reinicializar el segmento de memoria compartida. Puede ajustar el funcionamiento del cargador de caché, lo que puede resultar conveniente si dispone de discos muy rápidos y la carga es ligera. Puede hacer que se ejecute más rápido o, por el contrario, ralentizarlo un poco si almacena una caché con una enorme cantidad de archivos en discos lentos y no quiere que el cargador de caché consuma demasiados recursos de CPU al iniciarse NGINX.
28:07 Gestión de la caché de disco

Una vez que la caché está en memoria y los archivos se almacenan en el disco, existe el riesgo de que los archivos en caché a los que nunca se accede permanezcan allí indefinidamente. NGINX los almacenará la primera vez que los encuentre, pero, si no se reciben más solicitudes de un archivo, [el archivo] se quedará en el disco hasta que algún proceso lo elimine.
Ese algo es el administrador de caché; se ejecuta periódicamente, eliminando del disco los archivos a los que no se ha accedido durante un determinado periodo de tiempo, y borra archivos si la caché es demasiado grande y ha superado el tamaño declarado. Los elimina siguiendo el criterio de los menos usados recientemente. Puede configurar esta operación mediante los parámetros de la proxy_cache_path [directiva], del mismo modo que configura el cargador de caché:
- El tiempo de
inactividadpredeterminado es de 10 minutos. - El parámetro
max-sizeno tiene ningún límite predeterminado. Si se impone un límite demax-sizea la caché, es posible que en ocasiones se supere dicho límite, pero cuando se ejecute el gestor de la caché, este eliminará los archivos utilizados menos recientemente para volver a situarla por debajo de ese límite.
29:22 Eliminación de contenido del disco

Por último, puede haber ocasiones en las que quiera purgar contenido del disco. Si desea localizar un archivo y eliminarlo, es relativamente fácil si conoce las técnicas que hemos explicado anteriormente: procesar la clave de caché con md5sum o simplemente ejecutar una búsqueda recursiva con grep en todo el sistema de archivos para intentar identificar el archivo o los archivos que necesita eliminar.
Como alternativa, si utiliza NGINX Plus, puede usar la función de purga de caché integrada en el producto. Esta función permite tomar un parámetro concreto de la solicitud; por lo general, utilizamos un método denominado «PURGE» para identificar que se trata de una solicitud de purga de caché.
La purga la gestiona un controlador especial de NGINX Plus que examina el URI y elimina de la caché todos los archivos que coinciden con dicho URI. Se puede añadir un asterisco al final del URI para convertirlo en un prefijo. En este caso, vamos a utilizar la función de purga para eliminar todos y cada uno de los archivos servidos desde el host localhost a través del puerto 8001, aunque, por supuesto, también se podrían especificar subdirectorios.
Independientemente del método que utilice, puede eliminar en cualquier momento y con total seguridad archivos de la caché en disco o incluso ejecutar rm -rf en todo el directorio de caché. NGINX seguirá funcionando sin interrupciones y comprobando la presencia de archivos en el disco. Si no están, se producirá un fallo de caché. A continuación, NGINX recuperará el contenido del servidor de origen y volverá a almacenarlo en la caché en disco. Por tanto, si necesita eliminar archivos concretos de la caché, puede hacerlo siempre de forma segura, fiable y estable.
31:27 Control del almacenamiento en caché

Ya hemos visto cómo funciona el almacenamiento en caché, hemos analizado su implementación en NGINX y hemos estudiado en profundidad cómo almacena los archivos en disco para lograr un rendimiento similar al que obtiene con el contenido estático. Ahora vamos a profundizar un poco más en el almacenamiento en caché.
En sitios sencillos, puede activar el almacenamiento en caché y, por lo general, hará exactamente lo necesario para seguir ofreciendo el nivel de rendimiento y el comportamiento de la caché que desea. Sin embargo, siempre se pueden realizar optimizaciones y, a menudo, hay situaciones en las que el comportamiento predeterminado no coincide con el que desea.
Puede que sus servidores de origen no estén configurando correctamente las cabeceras de respuesta o que quiera reemplazar lo que especifican desde el propio NGINX. Hay infinidad de formas de configurar NGINX para ajustar con precisión el funcionamiento de la caché.
32:30 Almacenamiento en caché diferido

Puede retrasar el almacenamiento en caché. Esta es una situación muy habitual si dispone de un gran corpus de contenido al que, en su mayor parte, solo se accede una o dos veces por hora o por día. En ese caso, si tiene un folleto de su empresa que muy pocas personas leen, intentar almacenar ese contenido en caché suele ser una pérdida de tiempo. El almacenamiento en caché diferido permite establecer un umbral. Solo se almacenará una versión en caché de este contenido si se ha solicitado un determinado número de veces. Hasta que se alcance el umbral proxy_cache_min_uses, no se almacenará ninguna versión en la caché.
Esto le permite ser más selectivo con el contenido que se almacena en la caché. La caché en sí es un recurso limitado, normalmente condicionado por la cantidad de memoria disponible en el servidor, ya que conviene asegurarse de que permanezca cargada en memoria en la medida de lo posible. Por eso, suele ser recomendable limitar determinados tipos de contenido y almacenar en la caché únicamente las solicitudes más frecuentes.
La revalidación de la caché es una función que se ha añadido recientemente a NGINX Open Source y NGINX Plus. Modifica la funcionalidad If-Modified-Since para que, cuando NGINX necesite actualizar un valor almacenado en caché, no realice una simple solicitud GET para obtener una nueva versión de ese contenido, sino una solicitud GET condicional que indica: «Tengo una versión en caché que se modificó en esta fecha y hora concretas».
El servidor de origen puede responder con 304 No modificado, lo que en la práctica indica que la versión que tiene sigue siendo la más reciente. Esto ahorra ancho de banda de subida, ya que el servidor de origen no tiene que volver a enviar contenido que no ha cambiado, y también puede reducir las escrituras en disco. NGINX no tiene que transferir ese contenido al disco para después colocarlo en su lugar y sobrescribir la versión anterior.
34:45 Control del tiempo de caché

Dispones de un control preciso sobre el tiempo durante el que debe almacenarse en caché el contenido. Con bastante frecuencia, el servidor de origen servirá el contenido con cabeceras de caché adecuadas para los navegadores: almacenamiento en caché a largo plazo con solicitudes relativamente frecuentes para actualizar el contenido. Sin embargo, puede que prefieras que el proxy NGINX situado justo delante de tu servidor de origen actualice los archivos con algo más de frecuencia para detectar los cambios más rápidamente.
La carga aumenta enormemente si se reduce el tiempo de espera de la caché de los navegadores de 60 segundos a 10 segundos, pero aumenta muy poco si se reduce el tiempo de espera de la caché de NGINX de 60 segundos a 10 segundos. Por cada solicitud, esto añadirá cinco solicitudes más por minuto a los servidores de origen, mientras que, en el caso de los clientes remotos, todo dependerá del número de clientes que tengan activos elementos similares en el sitio.
Por tanto, puede anular la lógica y las indicaciones de su servidor de origen. Puede ocultar determinadas cabeceras o indicar a NGINX que las ignore: X-Accel-Expires, Cache-Control o Expires. También puede establecer un tiempo de caché predeterminado mediante la directiva proxy_cache_valid en la configuración de NGINX.
36:18 Almacenar en caché / No almacenar en caché

En ocasiones, puede que no quiera almacenar en caché contenido que el servidor de origen indica que se puede almacenar en caché, o quizá quiera asegurarse de omitir la versión del contenido almacenada en NGINX. Las directivas proxy_cache_bypass y proxy_no_cache le proporcionan ese grado de control.
Puede usarlas como método abreviado para indicar que, si está presente alguna de un conjunto determinado de cabeceras de solicitud, como la autorización HTTP, o algún parámetro de solicitud, se omita la caché, ya sea para actualizar automáticamente la caché de NGINX o para prescindir de ella por completo y recuperar siempre el contenido del servidor de origen.
Normalmente, se utilizan para tomar decisiones de almacenamiento en caché bastante complejas, en las que se evalúan minuciosamente los valores de las cookies y las cabeceras de autorización para controlar qué debe almacenarse en caché, qué debe obtenerse siempre del servidor de origen y qué no debe almacenarse nunca en la caché de NGINX.
37:25 Varias cachés

Por último, en implementaciones a muy gran escala, puede que le interese utilizar varias cachés dentro de una misma instancia de NGINX por un par de motivos. Podría aplicar distintas políticas de caché a los diferentes clientes de su proxy NGINX, en función de la naturaleza de cada sitio y de la importancia de su rendimiento, o incluso del plan concreto que tenga contratado cada cliente en un entorno de alojamiento compartido.
O puede que tenga varios discos en el host de NGINX y que lo más eficiente sea implementar una caché independiente en cada disco. La regla de oro es minimizar el número de copias de un disco a otro. Para ello, puede vincular una caché a cada disco y vincular al disco correcto el archivo temporal de cada proxy que utilice esa caché.
El funcionamiento habitual consiste en que, cuando NGINX recibe contenido de un proxy ascendente, lo transmite al disco, a menos que sea lo suficientemente pequeño como para caber en la memoria. Una vez que el contenido se ha transferido al disco, se mueve a la caché. Esta operación es muchísimo más eficiente si la ubicación de los archivos temporales (el disco donde se almacenan) coincide con el disco donde se almacena la caché.
39:07 Repaso rápido – ¿Por qué usar la caché?

Hemos hablado del almacenamiento en caché, de los métodos que utiliza NGINX, de su implementación en NGINX y de cómo se puede optimizar. Ahora que nos acercamos al final, hagamos un breve repaso para recordar por qué conviene almacenar contenido en caché. NGINX está instalado en 114 millones de sitios web de todo el mundo, y muchos de estos usuarios lo utilizan por sus funciones de aceleración web y almacenamiento de contenido en caché. [Nota del editor: esta cifra correspondía al momento en que se impartió el seminario web, en mayo de 2014.]
39:44 ¿Por qué es importante la velocidad de carga de las páginas?

Estas capacidades mejoran la velocidad de un sitio web —ofrecen a los usuarios finales una mejor experiencia—, y la velocidad de las páginas web es realmente muy importante. Durante años, los analistas han estudiado el comportamiento de los usuarios y han formulado lo que coloquialmente se conoce como la «regla de los N segundos». Este es el tiempo que un usuario medio está dispuesto a esperar a que una página se cargue y se muestre antes de aburrirse, perder la paciencia y marcharse a otro sitio web, el de la competencia.
A medida que los estándares han mejorado y las expectativas de los usuarios han aumentado cada vez más, el tiempo que están dispuestos a esperar se ha ido reduciendo progresivamente. Extrapolando esta tendencia mediante unos cálculos un tanto dudosos, se podría concluir que, hacia 2016, los usuarios tendrán un nivel de paciencia negativo.
40:46 Google cambió las reglas

Pero, en realidad, la tecnología nos ha adelantado. Google lo ilustró gráficamente hace un par de años al presentar Google Instant Search. Ahora, cuando escribes un término en el cuadro de búsqueda de Google, incluso antes de que termines de escribirlo, Google ya te muestra posibles resultados. Esto pone de manifiesto el enorme cambio que se ha producido en las expectativas respecto a la Internet moderna. Como ha señalado la propia Google, «ahora los usuarios esperan que las páginas web respondan igual que cuando se pasan las páginas de un libro»: con la misma rapidez, fluidez y naturalidad.
41:28 Los costes de un rendimiento deficiente

Si no alcanza ese nivel de rendimiento, los KPI asociados a su sitio web o servicio web pueden verse afectados de forma significativa. Por ejemplo, en lo que respecta a la tasa de clics en anuncios, Google constató que esta disminuía un 20 % cuando sus páginas de búsqueda tardaban medio segundo más en cargarse. En cuanto a los ingresos, Amazon aumentó deliberadamente el tiempo de carga de las páginas en intervalos de 100 ms para investigar el efecto de la lentitud y descubrió que los ingresos procedentes de los clientes afectados solían disminuir un 1 % por cada incremento de 100 ms.
Muchos otros analistas, sitios web e investigadores han observado efectos similares en las métricas de los sitios web, como el tiempo de permanencia en la página, la tasa de rebote, etc. Más recientemente, Google ha empezado a tener en cuenta la velocidad de las páginas al calcular su posición en los resultados de búsqueda. Al parecer, lo que cuenta es el tiempo hasta el primer byte. Cuanto más tarda en recibirse el primer byte al cargar una página, mayor es la penalización de su posición. Un sitio web puede verse perjudicado hasta el punto de no recibir ninguna visita por aparecer en la tercera, cuarta o quinta página de los resultados de búsqueda de Google.
43:00 El almacenamiento en caché de NGINX te permite

Las capacidades de almacenamiento en caché de NGINX permiten mejorar la experiencia del usuario final al reducir el tiempo hasta el primer byte y hacer que el contenido web se perciba más ágil y responda con mayor rapidez.
NGINX le permite consolidar y simplificar su infraestructura web. NGINX no es solo una caché web independiente. NGINX incluye un servidor web de origen y una puerta de enlace directa a API como FastCGI; además, NGINX Plus ofrece las funciones necesarias para crear un sofisticado balanceador de carga y controlador de entrega de aplicaciones preparado para entornos empresariales. Esto le permite consolidar varios componentes de red de su infraestructura web en uno solo —NGINX o NGINX Plus—, lo que proporciona soluciones más fiables, rápidas y fáciles de depurar.
NGINX permite aumentar la capacidad de los servidores al liberar a los servidores de origen de tareas repetitivas. De hecho, incluso en el caso de contenido que parece no poder almacenarse en caché (por ejemplo, la página principal de un blog), resulta útil almacenarlo en caché durante tan solo un segundo en el proxy NGINX.
Cuando cien usuarios solicitan el mismo contenido en el mismo segundo, NGINX lo reduce a una única solicitud al servidor de origen y sirve el contenido a esos usuarios desde su caché, garantizando que nunca tenga más de un segundo de antigüedad. Esto suele ser más que suficiente para un blog o un sitio web similar y, aun así, supone una enorme mejora del rendimiento, tanto por la reducción de la carga en los servidores ascendentes como por el ahorro en la gestión y el despliegue de la capacidad necesaria.
Por último, no olvide uno de los usos estratégicos de NGINX: protegerle frente a los fallos de los servidores de origen mediante la función «use stale» de la caché del proxy. Si funcionan con lentitud, devuelven errores o se produce algún tipo de fallo, NGINX puede recurrir a la versión local del contenido almacenada en caché y seguir utilizándola hasta que los servidores de origen se recuperen.
45:21 Reflexiones finales

El 38 % de los sitios web con más tráfico del mundo utilizan NGINX principalmente por sus funciones de aceleración web y almacenamiento en caché de contenidos. [Nota del editor: esta estadística era válida cuando se impartió el seminario web en mayo de 2014; consulte el valor actual aquí.] Para conocer más soluciones y obtener más información, consulte las entradas del blog y las fichas de funcionalidades en nginx.com, donde se describen las prestaciones de NGINX y NGINX Plus. Consulte también nuestra lista de seminarios web, que incluye no solo los próximos seminarios, sino también grabaciones de eventos anteriores de esta serie que se añadirán próximamente.
Y si desea explorar más a fondo estas funcionalidades, por supuesto, puede consultar la documentación y las soluciones disponibles en nginx.org y nginx.com, pero nada mejor que descargar el producto y probarlo. El producto de código abierto está disponible en nginx.org, mientras que el producto comercial con soporte, que incluye funciones adicionales de equilibrio de carga, entrega de aplicaciones, gestión y facilidad de uso, está disponible en nginx.com.
Bueno, muchas gracias a todos por vuestro tiempo y atención. Espero que esta presentación y este repaso del almacenamiento en caché de contenido en NGINX os hayan resultado útiles y esclarecedores.
Preguntas y respuestas
Empecemos a responder las preguntas y veamos qué tal nos va.
47:20 Solicitudes de intervalos de bytes
Tenemos una pregunta sobre las solicitudes de intervalos de bytes. Estas solicitudes se utilizan cuando un cliente solicita un contenido, pero solo necesita una parte de él. Por ejemplo, si se trata de un archivo de vídeo y el cliente solo necesita una parte del vídeo. Otro caso muy habitual es el de un archivo PDF: el usuario ha leído las cabeceras que contienen un índice del archivo PDF y el cliente solo quiere descargar un conjunto determinado de páginas. ¿Cómo funciona esto en la caché de contenido de NGINX?
El proceso es el siguiente. Cuando NGINX recibe una solicitud de intervalo de bytes para un recurso y el recurso completo ya se encuentra en la caché, NGINX responderá desde la caché con el intervalo de bytes solicitado por el cliente. Si el recurso no está en la caché, NGINX solicitará el recurso completo al servidor de origen y lo almacenará en la caché. Actualmente, en ese momento NGINX no atenderá la solicitud de intervalo de bytes y devolverá el recurso completo al cliente. En la mayoría de los casos, este comportamiento es aceptable.
Por ejemplo, si un cliente está descargando un documento PDF, su primera solicitud será de todos modos para obtener el documento completo. Solo si el documento se transmite en streaming, el cliente interrumpe la conexión y comienza a realizar solicitudes de intervalos de bytes. Por tanto, NGINX atiende las solicitudes de intervalos de bytes para el contenido almacenado en caché. Para el contenido que no está en caché, NGINX recupera todo el contenido del servidor de origen y, en esa ocasión, lo devuelve íntegramente al cliente.
49:13 Revalidación de la caché del proxy
Esta es una pregunta sobre la función de revalidación de la caché del proxy. Esta función permite que NGINX realice una solicitud GET condicional al servidor de origen para comprobar si el contenido ha cambiado. La pregunta es:
¿La revalidación de la caché del proxy tiene en cuenta los ETag o solo la fecha If-Modified-Since del contenido?
La respuesta es que solo comprueba la fecha If-Modified-Since del contenido y, en la práctica, suele ser recomendable incluir siempre If-Modified-Since en las respuestas y considerar los ETag opcionales, ya que no se gestionan de forma tan sistemática ni generalizada como la fecha de «última modificación» que se incluye en la respuesta.
50:07 Distribución de la caché entre discos de igual capacidad
¿Es posible que NGINX distribuya la carga de la caché de un único sitio entre varios discos iguales para obtener el máximo rendimiento?
Sí, es posible, aunque requiere algo de trabajo. Lo habitual es instalar varios discos sin RAID y, a continuación, implementar cachés independientes, cada una vinculada a un disco. Esto requiere cierta configuración adicional y dividir el tráfico. Si necesita ayuda para configurarlo, puede ponerse en contacto con nuestra comunidad, donde atenderemos su solicitud concreta, o bien, si utiliza NGINX Plus, contactar con nuestro equipo de soporte, que estará encantado de ayudarle.
50:50 Vary Encabezado
¿Tiene NGINX en cuenta la cabecera «Vary» para determinar si se produce un acierto o un fallo de caché?
No, NGINX no gestiona automáticamente las cabeceras Vary. Si esto supone un problema, basta con añadir la cabecera Vary a la clave de caché del proxy para que la clave única utilizada para almacenar la respuesta incluya el valor de la cabecera Vary. De este modo, se pueden almacenar varias versiones diferentes.
51:25 Primitivas de almacenamiento en caché
¿Se están respetando todas las primitivas y directivas de almacenamiento en caché?
En general, sí. Hay un par de casos límite, como las cabeceras «Vary», que no se respetan. En muchos casos, existe cierto margen a la hora de interpretar los requisitos de la RFC por parte de las distintas cachés. Siempre que ha sido posible, hemos optado por implementaciones fiables, coherentes y fáciles de configurar.
51:52 Encabezados y datos del servidor de origen
¿Se almacenan en caché tanto las cabeceras como los datos del servidor de origen?
Sí. Si recibes una respuesta de la caché, tanto las cabeceras como el cuerpo de la respuesta se almacenan en caché.
52:13 *‑Encoding Encabezados
Los valores de las cabeceras se almacenan en caché junto con el cuerpo de la respuesta, así que… me sorprendería bastante que NGINX no funcionara correctamente con las distintas combinaciones de Transfer-Encoding. Accept-Encoding suele implementarse mediante una cabecera Vary, por lo que también se aplican en este caso los comentarios anteriores sobre la necesidad de incluir las cabeceras Vary en la clave de caché (para los clientes que no admitan esta funcionalidad).
52:56 SPDY
¿Funciona el almacenamiento en caché con SPDY?
Por supuesto. Se puede considerar un proxy de frontend para NGINX, aunque en la práctica está estrechamente integrado en el núcleo de NGINX. Sí, SPDY funciona con el almacenamiento en caché.
53:15 Vary Encabezado, segunda ronda
Aquí tenemos otra pregunta sobre la cabecera Vary. Para confirmar, si utilizas respuestas con la cabecera Vary y archivos gzip, consulta algunos de los debates en Trac o en nuestro sitio de la comunidad para encontrar soluciones. El enfoque más habitual consiste en incluir la cabecera Vary en la clave de caché.
53:45 PageSpeed
P: ¿PageSpeed utiliza la caché de NGINX o su propio mecanismo de almacenamiento en caché?
Esa es una pregunta que deberías plantear a los desarrolladores de PageSpeed.
54:00 Otras cachés
P: ¿Cómo se comparan otras cachés de contenido con NGINX?
Las CDN son soluciones muy eficaces para almacenar contenido en caché. Las CDN se implementan como servicio, por lo que se dispone de un control más limitado sobre cómo se almacena el contenido en caché y cuándo caduca, pero son una herramienta sumamente eficaz para acercar el contenido a los usuarios finales. NGINX es una herramienta muy eficaz para acelerar las aplicaciones web y es muy habitual implementar ambas soluciones conjuntamente. En cuanto a las cachés independientes, como Varnish, también son tecnologías muy potentes que, en muchos aspectos, funcionan de forma similar a NGINX. Una de las ventajas de NGINX es que integra en una única solución los servidores de origen, las puertas de enlace de aplicaciones, el almacenamiento en caché y el balanceo de carga. Esto permite disponer de una infraestructura más sencilla y consolidada, que resulta más fácil de implementar y gestionar, así como de depurar y diagnosticar si surge algún problema.
Para ver el seminario web en el que se basa esta publicación, acceda a él aquí.
Para probar NGINX Plus, comience hoy mismo su prueba gratuita de 30 días o póngase en contacto con nosotros para hablar sobre sus casos de uso.
Sobre el autor

Artículos relacionados del blog
Únete a F5 NGINX en AppWorld 2024
Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.
Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.
Exposición de APIs en Kubernetes
La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».
NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.
Presentamos NGINX Plus R22
NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.
Presentamos NGINX Plus R17
NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.