Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Problema con caché por validación en Symfony2 con Varnish

5 de junio de 2014

Hola,

En mi empresa estamos desarrollando un proyecto en Symfony2 y nos encontramos en la fase de desarrollo del sistema de caché, utilizando para ello la caché estándar HTTP y el proxy reverso Varnish.

La mayor parte de las urls del proyecto utilizan el mecanismo de caché por expiración, pero en algunas necesitamos utilizar el mecanismo de caché por validación ya que hay ciertas acciones que necesitamos que se realicen en el backend aunque el recurso se encuentre cacheado. El problema que tenemos es que una vez que la url es cacheada por Varnish, en los siguientes accesos este devuelve el recurso cacheado al cliente y no envía la petición al backend, lo cuál no es correcto según el funcionamiento que debería tener la caché por validación (debería hacer una petición al backend para comprobar que el recurso no se haya modificado).

La implementación del mecanismo de caché en Symfony es bastante sencilla y básicamente hemos seguido los ejemplos de la documentación oficial, así que no sabemos qué puede estar pasando. No sé si alguien que tenga un poco de experiencia en el uso de Varnish con Symfony podría echarnos un cable. Adjunto un ejemplo del código utilizado más abajo.

Un saludo y gracias de antemano.

public function exampleControllerAction($slug, Request $request)
{
    $response = new \Symfony\Component\HttpFoundation\Response();
$response->setPublic();   // Queremos que la caché de los recursos expire cada día a las 00:00 horas $response->setLastModified(new \DateTime('today 00:00', new \DateTimeZone('Europe/Madrid')));   if ($response->isNotModified($request)) { // Si la url está cacheada hacemos algo en el backend $this->container->get('exameple.service')->doSomethingWithTheElement($slug); return $response; }   // Generamos el contenido de la url en el objeto response   return $response; }

Respuestas

#1

Aunque no voy a poder ayudarte con los detalles del problema técnico con Varnish, sí que me gustaría preguntarte algo: ¿merece realmente la pena utilizar la caché en este caso, sabiendo que la aplicación se va a ejecutar siempre que el usuario acceda a la página?

Al margen de esa pregunta, también me gustaría comentarte que en estos casos, algunos programadores optan por una estrategia diferente:

1. Utilizar la validación por expiración:

use Symfony\Component\HttpFoundation\Response;
 
public function exampleControllerAction($slug, Request $request)
{
    $response = new Response();
 
    // Queremos que la caché de los recursos expire cada día a las 00:00 horas
    $response->setExpires(
        new \DateTime('today 00:00', new \DateTimeZone('Europe/Madrid')
    ));
    $response->setPublic();
 
    // Si la url está cacheada hacemos algo en el backend
    $this->container->get('exameple.service')->doSomethingWithTheElement($slug);
 
    return $response;
}

2. Realizar una llamada con AJAX cada vez que se cargue la página en el navegador del usuario.

@javiereguiluz

5 junio 2014, 15:48
#2

La verdad es que no puedo asegurar con certeza que merezca la pena utilizar la caché en este caso, pero aplicando la caché con el mecanismo explicado pasamos de una petición que genera 24 consultas a la base de datos más el coste de la generación de los contenidos html de la página (renderización de templates y demás) a una petición que sólo genera 4 consultas a la base de datos y que no genera ningún contenido estático. Es cierto que el número de consultas se prodría reducir bastante utilizando bloques ESI, pero eso es algo que implicaría cambios profundos en la programación de la aplicación y que en este momento no nos planteamos.

Respecto a la posible solución que me comentas es algo que ya nos habíamos planteado pero por ahora preferimos tratar de hacer funcionar el mecanismo que comento, creo que es sólo cuestión de dar con las cabeceras http adecuadas.

De todos modos, gracias por la ayuda.

@beni0888

5 junio 2014, 19:16
#3

Una duda que tengo y que igual sí que me puedes resolver es la siguiente, ¿es necesario descomentar la siguiente línea del fichero app.php para utilizar varnish como proxy reverso?

// $kernel = new AppCache($kernel);

Es que este punto de la documentación no me queda claro, ya que dice que para utilizar el proxy reverso de symfony hay que descomentarla y que después el cambio a Varnish es transparente, pero no dice si hay que hacerlo cuando empiezas a utilizar directamente Varnish.

@beni0888

5 junio 2014, 19:33
#4

La línea que comentas hay que descomentarla cuando utilizas el proxy inverso de Symfony2 ... pero hay que volver a comentarla cuando utilices un proxy inverso externo, como por ejemplo Varnish. Si no, estarías utilizando en realidad dos proxys inversos encadenados.

Si consultas por ejemplo la documentación de eZPublish 5, que es una de las aplicaciones Symfony2 más complejas que existen, verás que te dicen que hay que comentar esa línea cuando utilizas Varnish:

By default your front controller (index.php) uses the built-in reverse proxy, EzPublishCache. In order to use Varnish, you need to deactivate it by commenting the line where EzPublishCache is instantiated.

@javiereguiluz

5 junio 2014, 21:44
#5

Ok Javier, gracias por la ayuda ;)

@beni0888

6 junio 2014, 8:46