ESI (Edge Side Includes)


Presentación de la problemática

En plataformas web más o menos complejas podemos encontrarnos con que cada página en sí está formada por diferentes "bloques" con diferentes características.

Por ejemplo, una página web que contenga una noticia en un periódico online puede estar formada por:


  • Índice de secciones del periódico.
  • Banner de publicidad
  • Artículo en sí.
  • Caja de las Top-10 noticias más visitadas
  • Comentarios de los usuarios.


Veamos un "diagrama" del anterior ejemplo:



Cachear este tipo de páginas es complicado a priori porque cada "bloque" necesitaría en realidad de un tiempo de vida específico:


  • Índice de secciones del periódico → TTL = 1 día.
  • Banner de publicidad → TTL = 0 (tiempo real, no se debe cachear).
  • Artículo en sí → TTL = 1 semana.
  • Caja de las Top-10 noticias más visitadas → TTL = 1 minuto.
  • Comentarios de los usuarios → TTL = 3 segundos (casi tiempo real).


Con una página de estas características, nos tenemos que amoldar al menor TTL disponible. En este caso, no podríamos cachearla si el banner debe de cambiar para cada usuario (por ejemplo, publicidad "contextual" basada en una cookie), o podríamos tomar como cacheo mínimo global 3 segundos si no nos importa que durante 3 segundos, todos los usuarios de nuestra web reciban el mismo banner y que éste pueda cambiar a los 3 segundos para el siguiente "ciclo de cacheo" (esto es lo que se conoce como microcacheo).


Lenguaje ESI

Edge Side Includes es un lenguaje diseñado para incluir vía HTTP fragmentos de páginas web en otras páginas web.

El principal objetivo de ESI son aquellas webs que comparten contenido entre páginas, como cajetines de comentarios, TOP-N, "widgets", marcadores, etc y que se tienen que generar una y otra vez para cada petición de las páginas, impidiendo además un correcto cacheo del resultado global.

ESI permite definir una "estructura" de página donde se incluyen el resto de páginas vía HTTP de forma que se puedan definir diferentes tiempos de cacheo para cada "bloque" que compone la página final.

Varnish soporta los siguientes 3 tags de ESI, y no :


  • esi:include
  • esi:remove
  • <!--esi ...-->


Estos tags serán ignorados dentro de comentarios HTML del tipo <!-- y -->.


Estructura de un documento ESI

La estructura de nuestro ejemplo en formato ESI podría ser similar a la siguiente:

<HTML>
<BODY>
<esi:include src="/cabecera.php"/>
<esi:include src="/ad_banner.php"/>
<esi:include src="/articulo.php"/>
<esi:include src="/top10.php"/>
<esi:include src="/comments.php"/>
</BODY>
</HTML>

La particularidad del código ESI es que cada "include" se reemplaza por la salida del fetch del elemento en cuestión, donde cada elemento es tratado como un elemento de caché diferente:


  • Cada elemento puede tener así su propio TTL / Expiración.
  • Cada elemento puede obtenerse de un backend diferente.
  • Cada elemento puede ser así mismo un nuevo bloque ESI (hasta cierto nivel de profundidad configurable).


Tras definir la página, tenemos que agregar el código VCL que permite este procesamiento:

sub vcl_fetch 
{
    if (req.url == "/noticia.html") 
    {
       # Iniciar procesado ESI para este documento:
       set beresp.do_esi = true;

       # Establecer TTL para el propio documento ESI en sí:
       set beresp.ttl = 24 h;
    } 
    elseif (req.url == "/cabecera.php") 
    {
       set beresp.ttl = 1d;
       return(lookup);
    }
    elseif (req.url == "/banner.php") 
    {
       return(pass);
    }
    # (etc...)
}

Las reglas para el uso de ESI son:


  • ESI requiere procesamiento por la CPU: no utilices ESI en todo el contenido web (especialmente en objetos binarios); sólo en aquellos sitios donde puedas obtener una mejora real.
  • No olvides la barra inversa (\) que cierra el tag XML ESI.
  • Se pueden tener construcciones ESI recursivas, hasta un máximo de max_esi_includes (5 por defecto).
  • No hay límite para la cantidad de inclusiones ESI por documento.
  • El destino de una inclusión ESI no debe tratarse en varnish con un pipe() (sería ignorado). Usa pass o lookup.
  • Actualmente sólo se soporta el atributo ESI "src". "Alt" y "OnError" (enlaces alternativos y comportamiento en caso de error) se ignoran.
  • Revisa los registros ESI_xmlerror en la salida de varnishlog para ver si hay problemas en el procesado ESI.




<Volver a Página de VARNISH>