7 de Julio, 2010

Varnish para acelerar nuestra web

Voy a explicar de forma sencilla como he implementado Varnish en este servidor, para acelerar algunas páginas que son casi estáticas, pero que se generan dinámicamente.

Ya hablamos sobre cómo acelerar la web con la caché, y aunque como servidor web trabajo con Cherokee, que es bastante eficiente gestionando su propia caché, poner a Varnish delante tiene cieras ventajas.

La primera de ellas es que este blog se sirve mediante un proxy HTTP (el servidor original es el de Tornado), y en ese caso concreto Cherokee por ahora no implementa caché :(.

Así que, por una parte me beneficio de las virtudes de Varnish para todo el servidor, y además consigo caché donde no tenía, a cambio de dedicar un poco de memoria al invento.

Mi servidor ahora funciona tal que así:

Diseño de la solución

Estoy trabajando con la versión 2.1.2 instalada desde fuentes, porque en la distro de mi servidor está la 2.1.0, y parece que merece la pena actualizar.

Hay que llevar cuidado con los requisitos, e instalar los paquetes de desarrollo de ncurses, porque el configure no se quejará, pero luego nos daremos cuenta de que no tenemos herramientas bastante útiles (como varnishstat o varnishtop).

Hay distintas formas de desplegar el caché, y a mi lo que me ha dado mejor resultado es:

  • Poner a Cherokee escuchando en el puerto 80, pero solo en 127.0.0.1. Esto es porque si usamos otro puerto, podemos tener problemas en algunas redirecciones (tengo pendiente ver si es un bug).
  • Poner a Varnish en el puerto 80, pero en la interfaz pública del servidor.

De esta forma, nuestro default.vcl empezará con:

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

Así indicamos donde estará nuestro backend (Cherokee en este caso).

Lo siguiente que he hecho ha sido ignorar las cookies en todos los contenidos que sé que no las utilizan, y por lo tanto los queremos cacheados:

sub vcl_recv {
        # cache static content, even when there are cookies
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|pdf)$") {
                unset req.http.Cookie;
                if (req.http.Accept-Encoding) {
                        remove req.http.Accept-Encoding;
                }
        }     
}

Todas esas extensiones sabemos que:

  • No cambian dinámicamente, y sobretodo no cambian por el hecho de haber una cookie. Por ejemplo, cuando trabajamos con usuarios autenticados.
  • Ya están comprimidos, así que podemos descartar el Accept-Encoding porque nunca los volveremos a comprimir, de forma que simplificamos qué se almacena en la caché.

Con esto ya es suficiente para arrancar Varnish.

Solo falta poner el servicio en el sistema de arranque (con init.d), porque instamamos desde fuentes. Por ejemplo, podemos usar:

#!/bin/sh

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Varnish"
NAME=varnish
DAEMON=/usr/local/sbin/varnishd
SCRIPTNAME=/etc/init.d/$NAME

test -f /etc/default/varnish && source /etc/default/varnish

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

case "$1" in
    start)
        cd /
        echo -n "Starting $DESC: $NAME"
        $DAEMON $OPTIONS 2>&1 >/dev/null < /dev/null
        echo "."
        ;;
  stop)
        echo -n "Stopping $DESC: $NAME"
        pkill varnishd
        echo "."
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop}" >&2
        exit 3
        ;;
esac

exit 0

Y en /etc/default/varnish ponemos los parámetros para el servicio:

OPTIONS="-f /usr/local/etc/varnish/default.vcl -s malloc,64M -a IP_PUBLICA:80"

He puesto IP_PUBLICA en lugar de mi IP, y he dedicado 64MB de memoria a la caché, que no será persistente en disco (ahora mismo no le veo mucho sentido a la persistencia de la caché, aunque si reinicio Varnish, no habrá nada cacheado).

En mi caso (Ubuntu Server), ejecuto update-rc.d como corresponde para que el servicio arranque con el sistema, y ya estamos listos para trabajar.

Ya anticipé hace unos días los buenos resultados que estaba obteniendo con Varnish, y a nivel de efectividad de la caché ya tengo algunos datos recogidos con varnishstat (herramienta incluída en el paquete de Varnish):

34863    Client requests received
11051    Cache hits
22190    Cache misses

Hay más datos, pero estos son los más relevantes para los últimos 5 días. Eso es un 31,69% de las peticiones servidas desde la caché, contra un 63.64% de peticiones que acabaron en Cherokee.

Estos valores no están mal, porque a fin de cuentas la mayoría de mis visitas van a las páginas nuevas en esta bitácora, que no son cacheables. Aún así, tengo pendiente prestarle más atención, a ver si puedo mejorar el resultado :P.

Finalmente comentar que he detectado un problema entre Varnish y Cherokee con el Keep-Live, y por ahora tendremos que usar Cherokee sin Keep-Alive para evitar posibles errores 503 en Varnish si se da el timeout. Curiosamente me he dado cuenta porque aguanto poco tráfico, y no es un problema si tenemos un servidor muy ocupado, donde sí sería realmente útil una caché como la que nos propociona Varnish :P.

Anotación por Juan J. Martínez, clasificada en: cache, cherokee.

Hay 2 comentarios

Gravatar

Un par de comentarios rápidos.

- Dentro de poco habrá cacheo en Cherokee. Podrás simplificar es diseño, y apuesto a que será bastante más rápido. :-)

- Lo del problema del proxy inverso, keep-alive y Varnish es problema de que éste último es un poquito “delicado” de más (debería poder manejar los RST). Veré a ver si puedo hacer que Cherokee se comporte como todo un caballero y haga siempre la desconexión a tres bandas.

por Alvaro Lopez Ortega, en 2010-07-08 17:11:03

Gravatar

Gracias por el comentario :)

Sí, sé que el caché en el proxy HTTP es una funcionalidad que viene de camino. Cuando esté lista, no dudes que la probaré :P

Respecto al problema Varnish/Cherokee, en realidad no tengo claro quién debe solucionarlo.

Creo que al final se reduce costes y a beneficios: coste de la corrección, y beneficio de ser interoperable, hablando igual para los dos proyectos.

por Juanjo, en 2010-07-08 17:22:37

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.

Algunas anotaciones relacionadas: