Indice dei contenuti dell'articolo:
Tra i CMS più diffusi, Drupal è probabilmente quello meglio predisposto per lavorare con Varnish. Dalla versione 8 in poi sa esattamente quali pagine contengono un certo contenuto e lo dichiara in ogni risposta, attraverso le cache tag. È un’informazione preziosissima per un reverse proxy: permette di tenere le pagine in cache molto a lungo e, quando un redattore modifica un articolo, di buttare via solo le pagine che lo mostrano.
Eppure, nella maggior parte delle installazioni che ci capita di analizzare, questa possibilità non viene usata. Si finisce con TTL brevissimi per paura di mostrare contenuti vecchi, oppure con svuotamenti totali della cache a ogni modifica. In entrambi i casi il server lavora molto più del necessario. In questo articolo vediamo come funzionano i livelli di cache di Drupal, come collegare le cache tag a Varnish e quali sono le trappole da evitare.
I livelli di cache di Drupal
Drupal ha due cache di pagina nel core, che lavorano dentro PHP:
- Internal Page Cache conserva le pagine intere per i visitatori anonimi. È veloce, ma ogni richiesta avvia comunque PHP e il bootstrap di Drupal;
- Dynamic Page Cache conserva le parti di pagina riutilizzabili e funziona anche per gli utenti autenticati, ricostruendo solo le porzioni personali.
Varnish si mette davanti a entrambe: quando ha la pagina in memoria, la richiesta non arriva nemmeno al server web e PHP non viene avviato. È il livello più veloce, quello che fa la differenza nei picchi di traffico. Il punto debole, se configurato senza le cache tag, è sapere quando una pagina è diventata vecchia.

Le cache tag: cosa sono e perché cambiano tutto
Ogni volta che Drupal costruisce una pagina tiene traccia di tutto ciò che ha usato: il nodo principale, i blocchi, i termini di tassonomia, gli utenti, le configurazioni. Ognuno di questi elementi ha un’etichetta, una cache tag, come node:42, taxonomy_term:3 o config:system.site. Quando un elemento cambia, Drupal invalida tutte le cache che portano quella tag.
Dentro Drupal questo meccanismo funziona da solo. Per estenderlo a Varnish servono due cose: che Drupal dichiari le tag nelle risposte, in un’intestazione HTTP che Varnish conserva insieme alla pagina, e che a ogni modifica Drupal chieda a Varnish di invalidare le pagine con quella tag. Il risultato è un comportamento che sembra impossibile: TTL lunghissimi, anche di un anno, e contenuti sempre aggiornati.

Collegare Drupal a Varnish: i moduli Purge
La documentazione di Drupal descrive una configurazione basata su due componenti:
- il modulo Purge, che raccoglie le invalidazioni in una coda e le smista;
- un purger, che le traduce in richieste per Varnish. La documentazione usa il Generic HTTP Purger, che aggiunge alle risposte l’intestazione
Purge-Cache-Tagse invia a Varnish richieste BAN; esiste anche il Varnish Purger, che usa l’intestazioneCache-Tags.
Il consiglio è di configurare due purger HTTP: uno di tipo “tag”, che invalida le pagine con una certa tag, e uno di tipo “everything”, da usare per lo svuotamento completo. Un’accortezza importante: non attivare insieme i sottomoduli di due purger diversi che aggiungono l’intestazione con le tag, altrimenti ogni risposta porta due copie dell’elenco e le intestazioni crescono inutilmente.
La coda di Purge va elaborata. La documentazione sconsiglia il processore “late runtime”, che lavora a ogni richiesta e pesa sul server, e suggerisce un cron ogni minuto (per esempio con Ultimate Cron) oppure, per prove e manutenzione, il comando drush p:queue-work.
La configurazione VCL
Una base per Varnish 6 o 7, costruita sulle indicazioni della documentazione di Drupal e del tutorial di Varnish per Drupal:
vcl 4.1;
acl purge {
"127.0.0.1";
"::1";
}
sub vcl_recv {
# Invalidazione per cache tag, solo dal server stesso
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(403, "Non autorizzato"));
}
if (!req.http.Purge-Cache-Tags) {
return (synth(400, "Purge-Cache-Tags mancante"));
}
ban("obj.http.Purge-Cache-Tags ~ " + req.http.Purge-Cache-Tags);
return (synth(200, "Ban eseguito"));
}
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
if (req.http.Authorization ||
req.url ~ "^/(admin|user|batch)" ||
req.url ~ "^/(update|cron|status).php" ||
req.url ~ "/ajax/") {
return (pass);
}
# Tiene solo i cookie di sessione di Drupal (SESS... e SSESS...)
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(S?SESS[a-z0-9]+)=", "; 1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie == "") {
unset req.http.Cookie;
} else {
return (pass);
}
}
return (hash);
}
sub vcl_backend_response {
set beresp.grace = 6h;
}
sub vcl_deliver {
# Le tag servono a Varnish, non ai browser
unset resp.http.Purge-Cache-Tags;
# Varnish conserva la pagina a lungo, il browser la ricontrolla sempre
if (resp.http.Cache-Control ~ "public") {
set resp.http.Cache-Control = "no-cache";
}
}
Il BAN usa solo intestazioni dell’oggetto in cache (obj.http), il che permette a Varnish di applicarlo in background senza attendere una nuova richiesta per ogni pagina. L’elenco degli indirizzi autorizzati va esteso solo se le invalidazioni partono da un altro server: lasciarlo aperto significa permettere a chiunque di svuotare la cache del sito.
Il TTL: lungo, perché tanto ci pensano le tag
In Drupal il tempo di vita delle pagine per i proxy si imposta in Configurazione > Sviluppo > Prestazioni, alla voce “Browser and proxy cache maximum age”, ed è quello che Drupal comunica nell’intestazione Cache-Control. Senza cache tag questo valore è un compromesso doloroso: alto significa contenuti vecchi, basso significa poca cache. Con le cache tag collegate a Varnish il compromesso sparisce, e il tutorial di Varnish per Drupal suggerisce di arrivare fino a un anno: ogni pagina resta in cache finché uno dei suoi contenuti non cambia davvero.
Il TTL dei proxy, ricordiamolo, vale anche per i browser se non si interviene. Per questo la VCL qui sopra, nel momento in cui consegna la pagina, sostituisce l’intestazione con Cache-Control: no-cache: Varnish conserva la pagina a lungo, mentre il browser la ricontrolla a ogni visita e il visitatore vede subito le modifiche.
Le trappole da conoscere
Intestazioni troppo lunghe. Su pagine complesse, con molti blocchi e viste, l’elenco delle cache tag può superare il limite predefinito di Varnish per una singola intestazione, che è di 8 KB. Quando succede, Varnish non riesce a leggere la risposta e restituisce un errore 503. La soluzione è aumentare il parametro http_resp_hdr_len e, della stessa misura, http_resp_size, che contiene l’intera intestazione della risposta.
Tag che si somigliano. Il BAN usa un’espressione regolare: una ricerca di node:42 trova anche node:420 e node:4200. Non è un errore grave, perché invalida qualche pagina in più del necessario, ma su siti grandi conviene configurare il purger perché delimiti le tag, così da colpire solo quelle giuste.
Contenuti personali nelle pagine pubbliche. Blocchi come “benvenuto Mario” o carrelli visibili agli anonimi rompono la cache di pagina. In Drupal vanno gestiti con i lazy builder o con le cache contexts corrette, altrimenti finiscono in cache e vengono mostrati a tutti.
Drupal 7. Le cache tag sono arrivate con Drupal 8. Sui siti Drupal 7 ancora in esercizio Varnish si usa con TTL più brevi o con moduli di invalidazione per URL, con risultati meno precisi: un motivo in più per pianificare la migrazione a Drupal 10 o 11.
Come verificare che funzioni
- Da visitatore anonimo, la seconda richiesta della stessa pagina deve arrivare da Varnish (intestazione
Agemaggiore di zero). - Modificando un nodo, dopo l’elaborazione della coda di Purge, le pagine che lo mostrano devono risultare aggiornate e le altre devono restare in cache.
- Con
varnishlogovarnishadm ban.listsi vedono i BAN arrivare con le tag giuste.
Conclusioni
Drupal porta con sé uno strumento che molti CMS non hanno: sa cosa c’è dentro ogni pagina. Collegare le cache tag a Varnish significa smettere di scegliere tra velocità e aggiornamento dei contenuti, e ottenere entrambe le cose: pagine servite in pochi millisecondi per quasi tutti i visitatori e modifiche visibili appena il redattore preme “salva”.
Sul nostro hosting Drupal configuriamo Varnish, moduli Purge e invalidazione per tag su misura del sito, e con il servizio di assistenza Varnish Cache interveniamo anche su infrastrutture esistenti.
