Guía de VCL: Varnish Configuration Language

En Tutoriales y Guías, Webmasters por

En artículos anteriores mostrábamos como instalar Varnish en Ubuntu y como configurar Varnish de forma básica y ahora toca hablar sobre VCL (Varnish Configuration Language) en esta guía de VCL. Este lenguaje VCL nos permite configurar Varnish de forma que tenemos control total sobre la lógica con la que procesa las peticiones.

Guía de VCL: Varnish Configuration Language

El lenguage de configuración VCL nos permite embeber código C y que será compilado a la hora de procesar el archivo de configuración VCL.

En muchos tutoriales de Varnish se emplea el termino backend para referirse al programa que está detrás de Varnish, nosotros en este tutorial en lugar de la palabra backend emplearemos la palabra Apache puesto que este suele ser uno de los backends más comunes.

Guía de VCL: Varnish Configuration Language

Lo primero es presentar las diferentes subrutinas por defecto de las que dispone el lenguaje VCL:

  • vlc_recv()
  • vcl_fetch()
  • vcl_pass()
  • vcl_hit()
  • vcl_miss()
  • vcl_deliver()
  • vcl_error()
  • vcl_pipe()
  • vcl_hash()

Lo que hay que tener claro es que cuando una petición HTTP llega a Varnish esta es procesada mediante las diferentes subrutinas presentes en nuestro archivo vcl de configuración. Más adelante veremos que el orden en el que se aplican estas subrutinas es muy concreto.

vlc_recv()

Cuando Varnish recibe una petición esta subrutina toma las decisiones de si aceptar o no la petición y en caso de aceptarla como va a procesarla. Cuando se recibe la petición Varnish crea automáticamente una serie de objetos para trabajar con la lógica en esta subrutina (en esta subrutina disponemos del objeto req para trabaja con el, por ejemplo con req.url, req.host, req.request, etc). Es la subrutina con la que controlamos la lógica al recibir la petición HTTP.

vcl_fetch()

Esta subrutina entra en acción después de que vlc_recv() ha aceptado la petición y Apache haya enviado la respuesta. Disponemos del objeto req para trabajar con el y aparece uno nuevo llamado beresp (el que podemos manipular según nuestras necesidades, por ejemplo podemos eliminar cookies, cambiar el TTL, etc). En esta subrutina lo que hacemos es alterar la respuesta que daría nuestro servidor. Es la subrutina con la que controlamos la lógica para manipular la respuesta HTTP.

Todavía hay más subrutinas de las que hablaremos más adelante, pero como estas son las dos más usadas, a continuación explico las diferentes acciones que podemos realizar dentro de cada subrutina (este orden de explicación me parece el mejor para entender las cosas más fácilmente). Estas acciones devuelven el control a Varnish de la petición y para ello se ejecutan mediante la salida de función return().
Las difierentes acciones que puede ejecutar Varnish son:

  • pass
  • pipe
  • lookup
  • deliver
  • hit_for_pass
  • restart

pass

A esta acción la llamamos de la forma return(pass); y lo que conseguimos es que la petición se envíe directamente a Apache (o nuestro backend) sin buscarla en el caché y por lo tanto la respuesta que recibe el usuario por parte de Varnish será una respuesta sin cachear. Esta acción se emplea en la subrutinas vlc_recv() (para la subrutina vcl_fetch() se emplea la acción hit_for_pass que es similar a pass y hablaremos de ella más adelante). Se recomienda emplear las acciones pass necesarias en la subrutina vlc_recv() en lugar de emplear los hit_for_pass en la subrutina vcl_fetch().

pipe

Es la acción que permite la comunicación directa entre el cliente (desde el navegador del usuario por ejemplo) y Apache, siendo Varnish unicamente un intermediario transparente, que no realiza ninguna función, sin procesar la petición HTTP ni la respuesta. Con esta acción no se crea ningún objeto de los que hablamos antes (req, bresp, etc) y Varnish no procesa las peticiones en absoluto, sólo hace de mensajero entre cliente y Apache. Esta acción es útil cuando se trata con archivos de video grandes (para que Varnish no los procese) o cuando se emplea algún método HTTP no soportado por Varnish, pero que Apache si entiende.

lookup

Esta acción sólo se puede emplear desde vcl_recv() y lo que le decimos a Varnish es que queremos emplear la caché para servir una respuesta al cliente. Se emplea de la forma return(lookup); y hay que aclarar que con esta acción se fuerza a Varnish a que busque en la caché aun cuando en la petición se solicite contenido no cacheado.

deliver

Se suele usar de de la forma return(deliver); y lo que conseguimos con esta acción es que Varnish devuelva el objeto cacheado al cliente (si es que existe en la caché). Se suele emplear desde vcl_fetch().

hit_for_pass

Es una acción similar a pass sólo que esta se usa desde vcl_fetch() y ademas tiene la particularidad de que con hit_for_pass se crea un objeto de tipo hitforpass con el que se cachea la decisión de no cachear. La decisión de no cachear se cachea durante la duración del ttl por defecto y ademas de no cachear no se ejecuta la subrutina vcl_pass() (sobre la cual hablaremos más adelante). Por este motivo insistimos en que es mejor emplear la acción pass desde vcl_recv().

restart

Vueleve a ejecutar la lógica VCL desde el principio de la subrutina vcl_recv() pero con la particularidad de que si hemos hecho algún cambio en el objeto req antes del restart estos se mantendrán. Cada vez que se reinicia se incrementa la variable req.restarts y se puede reiniciar hasta un máximo de veces indicado por el parámetro max_restarts.

Antes os hablamos de dos subrutinas vcl_recv() y vcl_fetch() ya que son las básicas y las que más se utilizan, pero tambien hay disponibles las siguientes subrutinas que quizás necesitemos usar en algún momento:

vcl_hash()

Permite alterar el hash que se utiliza para identificar el objeto dentro de la caché.

vcl_pipe()

Esta subrutina se ejecuta cuando se llama a la acción pipe.

vcl_pass()

Esta subrutina se ejecuta cuando se llama a la acción pass.

vcl_hit()

Se ejecuta cuando se llama a la acción lookup y ademas se encuentra un objeto cacheado valido.

vcl_miss()

Se ejecuta cuando se llama a la acción lookup y ademas no se encuentra un objeto cacheado valido.

vcl_error()

Esta subrutina se ejecuta cuando hay algún tipo de error interno.

vcl_deliver()

Esta subrutina se ejecuta cuando se llama a la acción deliver y se ejecuta justo antes de que el objeto cacheado sea enviado al cliente.

Ahora que ya tenemos en mente todas las acciones y subrutinas de Varnish y una idea aproximada de lo que podemos hacer con cada una es recomendable pararse un momento y ojear el siguiente esquema para hacernos una idea de como se procesa el archivo VCL.

Varnish esquema VCL

En el esquema podemos ver el flujo de ejecución de las diferentes subrutinas, desde que Varnish recibe la petición del cliente hasta que le devuelve una respuesta. Los nombres de las subrutinas tienen entre paréntesis las palabras “yours” o “default”, esto es para indicar la prioridad de que primero se ejecuta la lógica de la subrutina definida por el usuario y después la que haya definida por defecto.

Viendo el esquema nos hacemos una idea de como se comporta Varnish para procesar las peticiones y respuestas y nuestro objetivo será programar la lógica del archivo VCL para conseguir que Varnish se comporte de la forma que nosotros necesitamos, decidiendo que objetos se almacenan en cache, cuales no, etc… Para conseguir esto disponemos de reglas de coincidencia con las que podemos someter los diferentes objetos (req, bresp, etc…) a comprobaciones y así tomar decisiones. Estas reglas de coincidencia se definen con un condicional if como vemos en los siguientes ejemplos:

if (req.url ~ "^/phpMyAdmin") {
                ...
                ...
        }

if (req.request == "POST") {
                ...
                ...
        }

if (obj.hits > 0) {
                ...
                ...
        }

Cómo validar la configuración VCL de Varnish

Ahora que ya tenemos claro como crear un archivo VCL con su lógica ya podemos emplearlo en Varnish pero es recomendable antes de ponerlo en funcionamiento comprobar que compila correctamente ya que siempre podemos cometer algún error. Para hacer esta comprobación podemos ejecutar el siguiente comando:

varnishd -C -f /etc/varnish/default.vcl

Donde en este caso /etc/varnish/default.vcl es la ruta donde se encuentra el archivo VCL que queremos validar. Si se compila correctamente entonces podremos usarlo y si no compila nos mostrará un error indicando la línea en la que detectó el fallo para que podamos corregirlo.

Hasta aquí con la guía de VCL de Varnish y como configurar su lógica, sólo faltaría ver algunos ejemplos y analizarlos con detenimiento para una mayor toma de contacto y después ya estaríamos en condiciones de crear una configuración VCL a nuestra medida.