Catapulta la velocidad de tu sitio web con Varnish

Por Ricardo Cruz, 24 de Diciembre de 2018. Publicado en Software, Varnish. 10 minutos de lectura.

Mejorar el rendimiento de un sitio web te ayudará a pagar menos factura de hosting y a que Google te vea con mejores ojos frente a tu competencia. Varnish te puede ayudar, y mucho.

Si tu sitio web es eficiente, necesitarás menos servidores incluso en picos de tráfico puntuales. Siempre se habla de escalar tu web, ya sea en vertical (mejorando las características de tu servidor) o en horizontal (añadiendo más servidores para repartir la carga), pero nunca de cómo hacer las páginas más ligeras y eficientes.

Hoy te presento a Varnish.

¿Qué es Varnish?

Varnish es un Acelerador de Aplicaciones, o un Caching HTTP Reverse Proxy de código libre. Su función es guardar, en memoria caché, las peticiones que le llegan a tu servidor, para no tener que procesarlas una y otra vez.

Imagínate una web en la que listas billetes de avión a precios especiales, a partir de una serie de peticiones a los servidores de las compañías de vuelo con las que hayas conseguido llegar a un acuerdo. Una vez que tienes los resultados ordenados por precio ascendente, tendrías que generar, además, el HTML con el resultado.

Podrías llegar a pensar, de una manera muy acertada, que guardar los resultados de las compañías aéreas en una base de datos agilizaría todo el proceso. Y probablemente eso sería suficiente en casos en los que recibieras un buen puñado de peticiones por segundo a tus servidores, ¿100?, ¿200?… ¿y si recibes 2000 peticiones por segundo a una página o más?

Varnish te permite guardar el resultado final de la respuesta de tu servidor en su memoria RAM, de manera que volver a servir la misma petición sería cuestión de muy pocos milisegundos, tal y como ocurre al usar un CDN (Content Delivery Network).

Un CDN funciona de la misma manera. De hecho, los CDN funcionan con Varnish, o tecnología muy similar. La diferencia principal radica en que Varnish se puede programar para ajustarlo a las necesidades de tu aplicación.

Por defecto, las peticiones a tu servidor que llegan con cookies, se saltan la caché, para evitar mostrar datos de un usuario en el navegador de otro. Sin embargo, hay cookies que son ajenas a nuestro sistema, como las de Google Analytics, y que no influyen en el HTML que devolvemos.

Mediante su lenguaje de configuración, VCL, Varnish te permite ignorar cookies, ordenar los parámetros de una petición, limitar la cantidad de peticiones y un sinfín de otras posibilidades, gracias a las extensiones de la comunidad.

Por último, el uso de Varnish, junto a un CDN, es completamente compatible y recomendable.

Terminación de HTTPS

Lo primero que tienes que entender, al introducirte en el mundo de Varnish, es que únicamente soporta peticiones HTTP sin encriptar. Es por ello que, antes de poder procesar una visita a tu página web, tendrás que convertir ese tráfico encriptado, en una petición HTTP en texto plano.

Puedes hacerlo mediante el servidor web que uses, ya sea Apache, Nginx, o cualquier terminador SSL especializado, como Hitch, de la mano de los creadores de Varnish.

Para que puedas planificar tu infraestructura, ten en cuenta también que la comunicación entre Varnish y el servidor de la aplicación web, al igual que con los visitantes, deberá ser en texto plano.

Petición del usuario
   |
   | <- Tráfico encriptado
   |
Terminador SSL
   |
   | <- Tráfico sin encriptar
   |
Varnish
   |
   | <- Tráfico sin encriptar
   |
Tu página web

Si tus servidores web estuvieran en otra máquina, dependiendo de tu caso concreto, podrías tener que utilizar capas de comunicación seguras entre estos servidores. Por ejemplo, mediante una VPN o con IPSec.

Funcionalidad básica

Simplemente poniendo Varnish entre tus visitantes y tu servidor web, con su configuración por defecto, podrás notar que muchas de las peticiones las empezarás a servir en menos de 5ms, en lugar de 500ms, especialmente en sitios web donde el contenido es público (los visitantes no tienen que acceder a su cuenta para poder verlo).

En este ejemplo, vamos a configurar Varnish para acelerar las peticiones de un servidor web que ya existe en nuestro propio ordenador, que sirve sus peticiones en el puerto 80. La configuración sería la siguiente.

vcl 4.0;

backend default {
    .host = "127.0.0.1";
    .port = "80";
}

Por defecto, Varnish utiliza el puerto 6081, por lo que si accedieras a http://localhost:6081/ deberías poder ver la misma página que hay en http://localhost/

Jerga que debes aprender

En muchos tutoriales que encontrarás sobre Varnish, te encontrarás con algunos conceptos básicos que se darán por sentado. Hit, Miss, Saltarse la caché… ¿qué significan?

Todos giran en torno a la capacidad de Varnish para encontrar, o no, una petición HTTP almacenada en su memoria. Así, ”Hit” no es más que un éxito en esta importante misión, mientras que ”Miss” sería un fracaso, o un intento fallido. Al porcentaje de éxito se le denomina en inglés Hit Rate.

Un porcentaje de éxito, o Hit Rate, del 80%, en un sitio web que recibe 5000 peticiones por minuto, significará que Varnish estará sirviendo 4000 peticiones directamente desde la memoria RAM, sin pasar por tu servidor web. No significa necesariamente que hayamos reducido en un 80% el uso de CPU del servidor web, ya que no todas las peticiones son iguales.

Por otro lado, una petición que se ”salta la caché”, es una petición que ha fracasado a resolverse mediante la caché de Varnish, ya sea por una mala configuración o porque estemos recibiendo un ataque de Denegación de Servicio.

En general, a nivel de rendimiento, cuanto mayor sea el Hit Rate, mejor. Aunque puede ser que un Hit Rate excesivo se deba también a una mala configuración, mostrando incorrectamente peticiones cacheadas.

En cuestión de caché, TTL, Time To Live o, en español, Tiempo de vida, se refiere al tiempo que un recurso puede permanecer almacenado en la caché. Pasado ese tiempo, se considerará que ha expirado. Una imagen que se haya guardado en la memoria recientemente y que tenga un TTL de 1 minuto, se mostrará desde la caché si está dentro de ese tiempo, o se pedirá nuevamente al servidor si ya ha expirado.

Varnish Configuration Language

Los ficheros VCL son los ficheros de configuración de Varnish. La particularidad es que, a diferencia de un INI o un JSON, los VCL admiten condiciones lógicas, funciones y variables. Además son eficientes, se compilan antes de usarse e incluso puedes incluir código C en tu configuración.

Cada petición HTTP pasa por una serie de funciones dentro de estos ficheros, según el estado. Empiezan en vcl_recv(), donde podremos añadir, eliminar o editar sus cabeceras. Esta función además decidirá si la petición debería usar la caché de Varnish, o directamente ir a nuestro servidor web.

vcl 4.0;

backend default {
    .host = "127.0.0.1";
    .port = "80";
}

sub vcl_recv {
    if req.url ~ "/admin/" {
        return pipe;
    }

    return hash;
}

sub vcl_deliver {
    set resp.http.hola = "mundo";
}

En este ejemplo, las peticiones que vayan tanto a /admin/, como a /admin/users/, se saltarán por completo la caché de Varnish. En caso contrario, le añadiremos una cabecera HTTP “hola” con el contenido “mundo”, que podremos ver si inspeccionamos la respuesta del servidor.

El límite, al igual que con cualquier otro lenguaje de programación, está en tu propia imaginación y experiencia.

Como colofón a este breve apartado, los VCL se pueden recompilar y reemplazar en caliente, mientras Varnish sigue recibiendo peticiones, sin necesidad de reiniciar el servidor.

Utilizando módulos

Debido a la deliberada sencillez en su arquitectura, Varnish es extensible, mejorando la capacidad de configuración de tu sitio web mediante funciones extra para tus VCL.

Hay módulos oficiales de Varnish para los casos de uso más típicos, como parsear cookies, o limitar la cantidad de peticiones a tu API, por ejemplo, que son independientes de tu aplicación web.

Otros módulos, como Boltsort, permiten ordenar los parámetros de una URL para garantizar mayor cantidad de éxito al encontrar páginas almacenadas en la caché.

vcl 4.0;

import boltsort;

sub vcl_hash {
   set req.url = boltsort.sort(req.url);
}

Utilizando el código del ejemplo anterior, a nivel de caché, estas dos peticiones serían iguales:

  • https://rcruz.es/?a=hola&b=mundo
  • https://rcruz.es/?b=mundo&a=hola

Al ser ordenados los parámetros, Varnish siempre buscaría en la caché la primera opción.

Ignorando cookies externas

Por defecto, por seguridad, Varnish nunca guarda en su caché peticiones HTTP que contengan cookies. Almacenarlas podría provocar que las sesiones de tus usuarios se mezclasen. Puedes imaginarte el desastre que supondría revelar información privada de un usuario a otro, como podría ser el email, nombre real, dirección postal o mensajes privados.

Sin embargo, hay cookies que se usan únicamente en ciertas zonas de la web, o cookies de terceros, como las de Google Analytics, que se utilizan en el navegador web, siendo ignoradas por tu servidor.

No ignorarlas, provoca que el porcentaje de éxito en la búsqueda de la caché sea menor. Vamos a ver cómo solucionar este problema mediante el módulo cookie, incluido en el pack de módulos oficiales de Varnish.

vcl 4.0;

import cookie;

sub vcl_recv {
    if (req.http.cookie) {
        cookie.parse(req.http.cookie);
        cookie.filter_except("SESSION");
        set req.http.cookie = cookie.get_string();

        if (req.http.cookie == "") {
            unset req.http.cookie;
        }
    } 
}

Suponiendo que las sesiones en tu página web se manejen mediante una cookie llamada “SESSION”, en este ejemplo eliminamos todas las cookies, salvo ésta.

Podríamos haber usado cookie.delete en lugar de cookie.filter_except, pero si un atacante nos enviase cookies aleatorias, se saltaría nuestra caché, aumentando el uso de nuestros servidores. Por ello, es mejor siempre filtrar todo lo que no conozcamos.

Bloques ESI (Edge Side Includes)

He dejado para el final una de las características más interesantes de Varnish, los bloques ESI. Te permiten inyectar contenido de otra URL en un HTML estático. Algo así como un IFRAME, pero el resultado final es HTML normal y corriente.

En una página de tu web completamente estática, podrías incrustar un bloque ESI que muestre los últimos posts de tu blog, por ejemplo. Además, los bloques ESI pueden tener un tiempo de caché diferente al de la página que lo está llamando.

Usarlo es muy sencillo, supón que tienes dos páginas, índex.html y hola.html.

hola.html:

¡Mundo!

index.html

<h1>Hola <esi:include src="/hola.html" /></h1>

El resultado final, al entrar en index.html sería:

<h1>Hola ¡Mundo!</h1>

La magia de los ESI se aprecia cuando combinas páginas estáticas con contenido dinámico generado con tu lenguaje de programación preferido. Combinado con poder cachear esos bloques dinámicos, conseguirás una solución perfecta en cuanto a rendimiento.

Conclusión

En esta breve introducción hemos podido saborear algunos de los beneficios que nos ofrece este Acelerador HTTP. Emplear servicios dedicados a tareas concretas, como Redis para memoria compartida, o RabbitMQ para colas, es tan necesario como usar una base de datos.

Varnish no es diferente en este sentido, es una herramienta más que podrás llevar en tu cinturón, con la que podrás llevar el rendimiento de tu sitio web, o tu API, a otro nivel.

En próximos artículos veremos recetas concretas usando este software.

Sigue leyendo

Las Métricas de Oro para monitorizar tu web

17 de Diciembre de 2018. 5 minutos de lectura
Monitorizar

Si todo lo que se puede medir, se puede mejorar, tiene sentido aprender los puntos más importantes que deberías estar monitorizando para mejorar, de manera constante, tu sitio web.