Un Varnish gracioso

Varnish tiene una funcionalidad interesante llamada “grace” (gracia). Cuando se usa esta funcionalidad, el efecto es que, si el (o los) servidor web que está atrás de el no responden por unos segundos, Varnish puede responder al usuario una versión anterior de la página (si la tiene). Esto permite reducir altamente la cantidad de casos en los cuales un usuario se encuentra con una página tipo “Guru meditation”.

Para implementar esta funcionalidad, lamentablemente, no basta de simplemente poner req.grace = 30s o algo así, como la documentación básica de Varnish lo podría hacer pensar, sino es necesario implementar una configuración un poco más compleja. La página siguiente lo explica en muchos detalles: https://www.varnish-software.com/static/book/Saving_a_request.html

Principalmente, se trata de hacer algo de este tipo (es solo lo necesario, sabiendo que la parte del backend se declara para poder tener una noción de cuando consideramos que está enfermo – el objetivo de la sección .probe – asumiendo que el lector ya sabe de la configuración del módulo server-status de Apache, y estas cosas):

#1. Definición del backend
backend default {
  .host = "192.168.1.5";
  .port = "80";
  .probe = {
    .url = "/server-status";
    .interval = 3s;
    .window = 5;
    .threshold = 2;
  }
}
sub vcl_recv {
        #2. Definición del tiempo de grace cuando el backend está bien
        if (req.backend.healthy) {
                set req.grace = 10s;
        } else {
        #3. Definición del tiempo de grace cuando el backend no responde
                set req.grace = 10m;
        }
        # Activaremos lo siguiente luego
        #unset req.http.Cookie;
} 
#4. El tiempo de grace del backend mismo siempre debería ser 
# mayor o igual al tiempo de grace de Varnish. Este tiempo representa
# el tiempo durante el cual Varnish guarda una copia local de cualquier
# archivo, así que puede impactar mucho en uso de memoria. 
sub vcl_fetch { 
  set beresp.grace = 10m; 
}

Obviamente hay que entender bien lo que esto provoca para poder adaptarlo a cada caso de uso.

Aquí va un pequeño procedimiento de pruebas. Tengo una máquina Varnish local (192.168.1.4) y un servidor web (Apache, en 192.168.1.5) al cual llama el Varnish. Así estoy seguro de isolar los puntos de manera adecuada. Inicio sin niguna configuración particular de ttl en Varnish.

  1. Los dos sistemas (Varnish y Apache) están corriendo. Cargo una página de mi sitio. La veo. Todo bien.
  2. Apago el servidor web. Refresco la página (F5). Tengo un error Varnish (Guru meditation).

Ahora aplico los cambios sugeridos en vcl_recv y vcl_fetch (a parte de beresp.ttl que no defino) en mi configuración de Varnish:

  1. Cargo la página. Se ve.
  2. Apago el servidor web. Recargo (F5). Error. Re-inicio el servidor web. Se ve de nuevo.
  3. Agrego parámetros en Varnish para la gestión de Drupal (por si a caso).  Re-inicio Varnish.
  4. Cargo la página. Se ve.
  5. Apago el servidor web. Recargo (F5). Error. Re-inicio el servidor web. Se ve de nuevo.
  6. Agrego beresp.ttl = 1m; Reinicio Varnish.
  7. Cargo la página. Se ve.
  8. Apago el servidor web. Recargo (F5). Error. Re-inicio el servidor web. Se ve de nuevo.

Obviamente, es probable que Drupal esté afectando algo, ya que es dinámico. Probemos con algo más estático.

En el servidor web, me creo un archivo abc.html en la raíz.

  1. Cargo la página (estática abc.html). Se ve.
  2. Apago el servidor web. Recargo (F5). Error. Re-inicio el servidor web. Se ve de nuevo.

El problema es que los recursos que estamos pidiendo, los estamos pidiendo con Cookies activados. Esto depende de como está la configuración de Varnish acerca de los cookies, pero si, como yo, usan Drupal atrás, hay una serie de cosas que no van a funcionar simplemente porque tener un cookie implica que Varnish desconsidera poner estos recursos en “estado de gracia”. Por lo tanto, podemos hacer una prueba simple…

Dentro de la configuración de Varnish, vamos (para la prueba) a eliminar cualquier Cookie:

sub vcl_recv {
        #2. Definición del tiempo de grace cuando el backend está bien
        if (req.backend.healthy) {
                set req.grace = 10s;
        } else {
        #3. Definición del tiempo de grace cuando el backend no responde
                set req.grace = 10m;
        }
        unset req.http.Cookie;
}

Lo demás lo dejamos como indicado arriba. Ahora hacemos una prueba.

  1. Cargo la página (raíz del sitio, página dinámica). Se ve.
  2. Apago el servidor web. Recargo (F5). Se ve!!!

Esto lo logramos porque ninguna regla posterior invalida el caché de Varnish.

Ahora obviamente hay que afinar. El problema con Drupal es que, si uno lo deja, agrega un paquete de Cookies que se vuelve incontrolable. Para analizarlos, podemos usar Firebug, ponernos en la pestaña  de Cookies, y recargar la página. A todo lo que *no* sea drupal_uid, DRUPAL_UID o drupal_user (si usa authcache, puede ser un caso particular) puede ser eliminado.

Comments

Enlace permanente

Es mejor defirnir un tiempo de gracia de la siguiente forma:

set req.http.Surrogate-Capability = “abc=ESI/1.0”;
set req.grace = 120s;
set req.backend = default;

if (req.url ~ “^/server_status.php$”) {
return (pass);
}

Es mas limpio

sls