Varnish Cache per PrestaShop: Quando i moduli Full Page Cache non bastano

411 visualizzazioni

Cos'è Varnish e perché è importante per PrestaShop

Varnish Cache è un reverse proxy HTTP che si posiziona tra il tuo server web e internet, servendo copie cachate delle pagine senza mai toccare PHP o MySQL. Quando un visitatore richiede una pagina che Varnish ha in cache, la risposta arriva direttamente dalla memoria in microsecondi. PHP non viene eseguito. MySQL non riceve alcuna query. Il server web nota appena che la richiesta è avvenuta.

Questo è fondamentalmente diverso da come funzionano i moduli di full page cache (FPC) basati su PHP in PrestaShop. Un modulo FPC viene comunque eseguito all'interno di PHP. La richiesta raggiunge Apache o Nginx, PHP si avvia, PrestaShop si inizializza (caricando la configurazione, stabilendo connessioni al database, analizzando le rotte), e poi il modulo FPC intercetta la richiesta prima che la logica completa del controller venga eseguita, servendo un file HTML memorizzato nella cache. Sebbene sia significativamente più veloce rispetto al rendering della pagina da zero, comporta comunque l'avvio di PHP e il caricamento del framework PrestaShop. Questo overhead, tipicamente di 50-200 millisecondi anche per un cache hit, si accumula sotto carico.

Varnish elimina completamente questo overhead. Un cache hit di Varnish viene servito in 1-5 millisecondi. Con traffico elevato, la differenza è drammatica. Un negozio PrestaShop che fatica a gestire 100 utenti simultanei con un modulo FPC può servire migliaia di utenti simultanei con Varnish, perché la stragrande maggioranza delle richieste non raggiunge mai il backend PHP.

Quando i moduli PHP Full Page Cache sono sufficienti

Prima di investire in Varnish, vale la pena capire quando un modulo FPC basato su PHP è sufficiente. Per molti negozi PrestaShop, lo è.

Se il tuo negozio riceve meno di 50.000 visualizzazioni di pagina giornaliere, un modulo FPC ben configurato gestirà il carico senza problemi. La complessità aggiuntiva di Varnish non è giustificata quando il tuo server ha capacità di riserva. Se i tempi di risposta del server con FPC sono costantemente sotto i 200 millisecondi, i tuoi visitatori stanno già ottenendo caricamenti rapidi delle pagine. Il collo di bottiglia a quel punto è probabilmente il rendering frontend (CSS, JavaScript, immagini) piuttosto che il tempo di risposta del server.

I moduli FPC gestiscono alcuni scenari specifici di PrestaShop con più eleganza rispetto a Varnish perché vengono eseguiti all'interno dell'applicazione. Possono verificare se un utente è loggato, se il carrello contiene articoli e se determinati contenuti dinamici necessitano di personalizzazione — tutto all'interno dello stesso processo PHP. Con Varnish, questi controlli devono essere gestiti tramite l'ispezione dei cookie e regole di variazione della cache, il che aggiunge complessità alla configurazione.

Considera Varnish quando il tuo negozio gestisce regolarmente picchi di traffico (vendite flash, campagne marketing, picchi stagionali) che sovraccaricano la tua capacità PHP, quando hai bisogno di tempi di risposta inferiori a 10 ms per ragioni SEO o di esperienza utente, quando il budget per l'hosting è limitato e devi servire più traffico con lo stesso hardware, o quando il tuo negozio serve un'alta percentuale di navigazione anonima (pagine di categoria, pagine prodotto) rispetto all'attività del carrello e del checkout.

Come funziona Varnish: il flusso delle richieste

Comprendere il flusso delle richieste attraverso Varnish è essenziale per configurarlo correttamente con PrestaShop.

Arrivo della richiesta

Quando un visitatore richiede una pagina, la richiesta raggiunge prima Varnish (Varnish è in ascolto sulla porta 80 o 443 se la terminazione SSL è gestita da un proxy frontend). Varnish esamina la richiesta: l'URL, il metodo HTTP, i cookie e gli header.

Ricerca nella cache

Varnish controlla la sua cache alla ricerca di una risposta memorizzata che corrisponda a questa richiesta. La chiave della cache è tipicamente basata sull'URL e su header selezionati. Se una risposta corrispondente esiste e non è scaduta, Varnish la serve direttamente. Questo è un cache hit. La risposta viene inviata al visitatore e il server backend non viene mai contattato.

Cache miss

Se non esiste una risposta cachata corrispondente, Varnish inoltra la richiesta al server backend (Apache o Nginx che esegue PrestaShop). PrestaShop elabora la richiesta normalmente, genera la risposta HTML e la invia a Varnish. Varnish memorizza la risposta nella sua cache (se la risposta è cacheable) e la inoltra al visitatore. Le richieste successive per la stessa pagina verranno servite dalla cache.

Invalidazione della cache

Quando i dati del prodotto cambiano, i prezzi vengono aggiornati o il contenuto viene modificato, la versione in cache diventa obsoleta. Varnish deve essere informato di scartare la vecchia versione cachata in modo che ne recuperi una fresca dal backend. Questa è l'invalidazione della cache, ed è la parte più difficile di qualsiasi sistema di caching da implementare correttamente.

Configurazione VCL per PrestaShop

Varnish Configuration Language (VCL) è un linguaggio specifico di dominio che controlla come Varnish gestisce le richieste. Una configurazione VCL corretta per PrestaShop deve gestire diversi comportamenti specifici di PrestaShop.

Definizione del backend

La definizione del backend indica a Varnish dove inoltrare i cache miss. Per una tipica configurazione PrestaShop dove Apache o Nginx gira sullo stesso server sulla porta 8080:

backend default {
  .host = "127.0.0.1";
  .port = "8080";
  .connect_timeout = 5s;
  .first_byte_timeout = 60s;
  .between_bytes_timeout = 10s;
}

I timeout sono importanti. Le pagine PrestaShop possono richiedere diversi secondi per essere generate con cache fredda, specialmente le pagine di categoria con molti prodotti. Impostare first_byte_timeout troppo basso fa sì che Varnish restituisca un errore 503 prima che PrestaShop abbia finito di generare la pagina.

Gestione dei cookie e delle sessioni

I cookie sono la sfida più grande quando si fa caching di PrestaShop con Varnish. PrestaShop imposta diversi cookie per impostazione predefinita, e Varnish tratta qualsiasi richiesta con cookie come non cacheable a meno che non venga istruito diversamente. Se non gestisci i cookie nel tuo VCL, Varnish non cacheerà praticamente nulla.

PrestaShop imposta questi cookie sulla maggior parte delle richieste: il cookie di sessione (tipicamente chiamato PrestaShop-xxxx), i cookie relativi al carrello, i cookie di Google Analytics (_ga, _gid, _gat) e vari cookie di tracciamento da strumenti di marketing. Di questi, solo il cookie di sessione PrestaShop è importante per il comportamento della cache. I cookie di analytics e tracciamento dovrebbero essere rimossi dalla richiesta prima della ricerca nella cache in modo che non impediscano il caching.

Nella subroutine VCL vcl_recv, rimuovi i cookie non essenziali:

sub vcl_recv {
  # Rimuovi cookie di Google Analytics e altri traccianti
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_ga|_gid|_gat|__utm[a-z]+|_fbp|_gcl_[a-z]+)=[^;]*", "");
  # Rimuovi header cookie vuoto
  if (req.http.Cookie ~ "^\s*$") {
    unset req.http.Cookie;
  }
}

Decidere cosa cachare

Non tutte le pagine PrestaShop dovrebbero essere cachate. Il VCL deve distinguere tra richieste cacheable e non cacheable.

Cacha sempre: Pagine prodotto per visitatori anonimi, pagine di elenco categorie, pagine CMS (chi siamo, termini, contatti), la homepage, pagine di produttori e fornitori, pagine della sitemap.

Non cachare mai: La pagina del carrello, le pagine del checkout (tutti i passaggi), l'area account cliente (ordini, indirizzi, informazioni personali), le pagine di login e registrazione, qualsiasi pagina per un cliente loggato, richieste POST, richieste AJAX che modificano lo stato (aggiungi al carrello, aggiorna quantità).

La logica VCL per questo tipicamente controlla il percorso URL e la presenza di cookie di sessione:

sub vcl_recv {
  # Non cachare le richieste POST
  if (req.method == "POST") {
    return (pass);
  }
  # Non cachare l'area admin
  if (req.url ~ "^/admin") {
    return (pass);
  }
  # Non cachare checkout e carrello
  if (req.url ~ "(cart|order|login|my-account|module/)" ) {
    return (pass);
  }
  # Non cachare se il cliente ha articoli nel carrello
  if (req.http.Cookie ~ "PrestaShop-") {
    return (pass);
  }
  return (hash);
}

Impostare la durata della cache

Nella subroutine vcl_backend_response, controlli per quanto tempo Varnish cacha ogni risposta. PrestaShop invia header Cache-Control che tipicamente indicano no-cache o private perché presume che ogni risposta possa contenere contenuto personalizzato. Devi sovrascriverli per le pagine che sai essere sicure da cachare:

sub vcl_backend_response {
  # Cacha pagine prodotto e categoria per 1 ora
  if (bereq.url ~ "^/([0-9]+-|[a-z]+-[0-9]+)") {
    set beresp.ttl = 1h;
    unset beresp.http.Set-Cookie;
  }
  # Cacha asset statici per 1 giorno
  if (bereq.url ~ "\.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf)$") {
    set beresp.ttl = 1d;
    unset beresp.http.Set-Cookie;
  }
}

Rimuovere Set-Cookie dalle risposte cachate è critico. Se una risposta cachata include un header Set-Cookie, Varnish non la cacheerà per impostazione predefinita, e anche se forzato a cachare, imposterebbe lo stesso cookie di sessione per ogni visitatore, causando session hijacking.

Invalidazione della cache con richieste PURGE

Quando il prezzo di un prodotto cambia, viene aggiunto un nuovo prodotto o il contenuto viene aggiornato, la versione cachata deve essere invalidata. Varnish supporta le richieste PURGE: un metodo HTTP speciale che indica a Varnish di rimuovere un URL specifico dalla sua cache.

Configurare il supporto PURGE

Aggiungi la gestione PURGE al tuo VCL:

acl purge {
  "127.0.0.1";
  "localhost";
}

sub vcl_recv {
  if (req.method == "PURGE") {
    if (!client.ip ~ purge) {
      return (synth(405, "Not allowed."));
    }
    return (purge);
  }
}

L'ACL limita le richieste PURGE a localhost, impedendo agli utenti esterni di svuotare la tua cache.

Attivare i purge da PrestaShop

PrestaShop non invia nativamente richieste PURGE. Hai bisogno di un modulo o di un hook personalizzato che rilevi quando il contenuto cacheable cambia e invii una richiesta PURGE a Varnish. Il modulo si aggancia agli eventi PrestaShop come actionProductUpdate, actionCategoryUpdate e actionCMSPageUpdate. Quando questi eventi si attivano, il modulo invia una richiesta HTTP PURGE all'URL corrispondente sul server Varnish.

Per un aggiornamento di prodotto, il modulo dovrebbe purgare l'URL del prodotto, gli URL delle categorie a cui appartiene il prodotto (perché le pagine elenco delle categorie mostrano prezzi e disponibilità dei prodotti) e potenzialmente la homepage se mostra prodotti in evidenza. Questa cascata di purge è necessaria per evitare che dati obsoleti appaiano in qualsiasi punto del sito.

Invalidazione basata su BAN

Per scenari in cui molti URL devono essere purgati contemporaneamente (un aggiornamento prezzi a livello di sito, un cambio di design, un nuovo banner promozionale), le singole richieste PURGE sono impraticabili. Varnish supporta i ban, che sono regole di invalidazione basate su pattern. Un ban indica a Varnish di scartare qualsiasi oggetto cachato che corrisponda a un pattern:

sub vcl_recv {
  if (req.method == "BAN") {
    if (!client.ip ~ purge) {
      return (synth(405, "Not allowed."));
    }
    ban("req.url ~ " + req.http.X-Ban-Pattern);
    return (synth(200, "Banned."));
  }
}

Inviare una richiesta BAN con l'header X-Ban-Pattern: /category/ invaliderebbe tutte le pagine di categoria cachate in un'unica operazione.

Edge Side Includes (ESI) per blocchi dinamici

Molte pagine PrestaShop contengono un mix di contenuto statico e dinamico. L'elenco prodotti in una pagina di categoria è lo stesso per ogni visitatore, ma l'header che mostra il conteggio del carrello è personalizzato. Senza ESI, non puoi cachare la pagina affatto perché l'header dinamico rende l'intera risposta specifica per il visitatore.

Gli Edge Side Includes risolvono questo problema permettendo di contrassegnare sezioni della pagina come frammenti recuperati separatamente. Varnish assembla la pagina finale da frammenti cachati e non cachati.

Come funziona ESI

Nel tuo template Smarty, invece di renderizzare direttamente il widget del carrello, includi un tag ESI:

<esi:include src="/module/cartwidget/ajax" />

Quando Varnish elabora la pagina cachata, incontra il tag ESI e effettua una richiesta separata al backend per quel frammento. Il corpo principale della pagina viene servito dalla cache, mentre il widget del carrello viene recuperato fresco da PrestaShop. La risposta assemblata include sia il corpo cachato che il widget del carrello aggiornato.

Abilita l'elaborazione ESI nel tuo VCL:

sub vcl_backend_response {
  set beresp.do_esi = true;
}

Considerazioni ESI per PrestaShop

Implementare ESI richiede la modifica dei template PrestaShop per separare il contenuto dinamico in frammenti compatibili con ESI. Ogni frammento necessita del proprio endpoint URL che restituisce solo l'HTML per quel blocco. I frammenti che sono tipicamente dinamici e necessitano di trattamento ESI includono il widget riepilogo carrello (conteggio articoli, totale), il saluto al cliente ("Ciao, Giovanni"), eventuali raccomandazioni di prodotti personalizzate, il link login/logout e i prodotti visualizzati di recente.

Lo sforzo richiesto per implementare ESI correttamente è significativo. Ogni frammento dinamico necessita di un controller dedicato, i template richiedono ristrutturazione e le regole di caching per ogni frammento necessitano di regolazione individuale. Questo è uno dei motivi per cui Varnish è considerato un'ottimizzazione avanzata — funziona meglio quando l'applicazione è progettata tenendolo a mente.

Controlli di salute del backend

Varnish può monitorare lo stato del tuo server backend e agire quando diventa non disponibile. Questo viene configurato nella definizione del backend:

backend default {
  .host = "127.0.0.1";
  .port = "8080";
  .probe = {
    .url = "/ping.php";
    .timeout = 2s;
    .interval = 5s;
    .window = 5;
    .threshold = 3;
  }
}

Varnish invia una richiesta a /ping.php ogni 5 secondi. Se 3 degli ultimi 5 controlli falliscono, Varnish contrassegna il backend come malato. Mentre il backend è malato, Varnish può servire contenuto cachato obsoleto (modalità grace) invece di restituire errori ai visitatori. Questo significa che il tuo negozio rimane parzialmente disponibile anche quando il backend PHP va in crash o si riavvia.

La configurazione della modalità grace determina per quanto tempo Varnish servirà contenuto obsoleto:

sub vcl_backend_response {
  set beresp.grace = 6h;
}

Con un grace di 6 ore, se il tuo backend va giù, i visitatori vedranno pagine cachate (anche se vecchie di 6 ore) invece di pagine di errore. I prezzi dei prodotti potrebbero essere leggermente non aggiornati, ma il negozio resta funzionante mentre risolvi il problema del backend.

Benchmark delle prestazioni

La differenza di prestazioni tra nessuna cache, PHP FPC e Varnish è sostanziale e misurabile.

Senza cache (PrestaShop base): Una tipica pagina prodotto PrestaShop richiede 200-800 millisecondi per essere generata, a seconda dell'hardware del server, del numero di moduli caricati e del numero di query al database. Sotto carico, i tempi di risposta aumentano perché i worker PHP sono saturi. Un singolo server può gestire 20-50 utenti simultanei prima che i tempi di risposta diventino inaccettabili.

Modulo PHP FPC: I cache hit vengono serviti in 30-100 millisecondi perché PHP si avvia comunque e il framework si inizializza parzialmente. Sotto carico, le prestazioni sono molto migliori perché le risposte cachate richiedono un tempo di elaborazione PHP minimo. Un singolo server può gestire 200-500 utenti simultanei a seconda della configurazione. I cache miss richiedono comunque il tempo completo di rendering.

Varnish: I cache hit vengono serviti in 1-5 millisecondi. Sotto carico, Varnish stesso può gestire migliaia di connessioni simultanee perché è scritto in C ed è progettato specificamente per questo tipo di carico. Il server backend gestisce solo i cache miss, che sono una piccola frazione del traffico totale in un sistema correttamente configurato. Lo stesso hardware che fatica con 50 utenti simultanei senza caching può gestirne 5.000 o più con Varnish.

Questi numeri illustrano perché Varnish vale la complessità di configurazione per i negozi ad alto traffico. Il miglioramento delle prestazioni non è incrementale — è di un ordine di grandezza.

Requisiti di hosting

Varnish ha requisiti di hosting specifici che non tutti gli ambienti di hosting PrestaShop possono soddisfare.

Accesso al server

Hai bisogno dell'accesso root per installare e configurare Varnish. I piani di hosting condiviso non supportano Varnish perché richiede un proprio processo in ascolto su una porta che intercetta tutto il traffico HTTP. Hai bisogno di un VPS, server dedicato o istanza cloud dove controlli l'intero stack del server.

Memoria

Varnish memorizza la sua cache nella RAM. La quantità di RAM necessaria dipende dal numero di pagine uniche nel tuo catalogo e dalla dimensione di ogni risposta cachata. Una formula approssimativa: il numero di pagine cacheabili moltiplicato per la dimensione media della pagina fornisce la dimensione minima della cache. Un negozio con 5.000 prodotti, 200 categorie e una dimensione media della pagina di 50KB necessita di circa 260MB di cache RAM. Aggiungi l'overhead per Varnish stesso e dovresti allocare almeno 512MB. Per cataloghi più grandi, 1-2GB è la norma.

Configurazione delle porte

In una configurazione standard, Varnish è in ascolto sulla porta 80 (la porta HTTP predefinita) e inoltra i cache miss al server web su una porta diversa (comunemente 8080). Questo significa che devi riconfigurare Apache o Nginx per ascoltare sulla porta 8080 invece che sulla 80. Se usi HTTPS (e dovresti), tipicamente metti Nginx davanti a Varnish per gestire la terminazione SSL: Nginx sulla porta 443 termina SSL e inoltra a Varnish sulla porta 80, che inoltra i cache miss ad Apache o PHP-FPM sulla porta 8080.

Esempio di configurazione Docker

Eseguire Varnish in Docker insieme a un container PrestaShop è un modo pulito per aggiungere Varnish a una configurazione esistente senza modificare il sistema host.

Configurazione Docker Compose

Una configurazione Docker Compose di base con Varnish, Nginx per SSL e PrestaShop:

services:
  varnish:
    image: varnish:7.4
    ports:
      - "80:80"
    volumes:
      - ./varnish/default.vcl:/etc/varnish/default.vcl:ro
    environment:
      - VARNISH_SIZE=512m
    depends_on:
      - prestashop
  prestashop:
    image: prestashop/prestashop:8
    expose:
      - "80"
    environment:
      - DB_SERVER=db
  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=secretpassword
      - MYSQL_DATABASE=prestashop

In questa configurazione, Varnish è il punto di ingresso sulla porta 80. Il container PrestaShop non espone la sua porta all'host, solo alla rete Docker. L'host del backend VCL sarebbe prestashop (il nome del servizio Docker) sulla porta 80.

VCL per Docker

La definizione del backend VCL per Docker usa il nome del servizio invece di localhost:

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

Il DNS interno di Docker risolve il nome del servizio nell'IP del container. Il resto della configurazione VCL rimane lo stesso di una configurazione senza Docker.

Storage della cache in Docker

Per impostazione predefinita, l'immagine Docker di Varnish usa lo storage in memoria (malloc), che è ideale per le prestazioni. La variabile d'ambiente VARNISH_SIZE controlla quanta memoria Varnish alloca per la sua cache. Imposta questo valore su uno che rientri nei limiti di memoria del tuo container lasciando spazio per il processo Varnish stesso.

Per una cache persistente che sopravviva ai riavvii del container, puoi usare lo storage basato su file montando un volume, ma è raramente necessario. La cache si scalda rapidamente (entro pochi minuti dalla ricezione del traffico) e lo storage su file è più lento di quello in memoria.

Monitoraggio delle prestazioni di Varnish

Varnish fornisce strumenti integrati per monitorare le prestazioni della cache.

Il comando varnishstat mostra statistiche in tempo reale incluso il tasso di hit della cache, le connessioni al backend e l'utilizzo della memoria. La metrica più importante è il tasso di hit, che dovrebbe essere dell'85% o superiore per una configurazione ben configurata. Se il tuo tasso di hit è sotto il 70%, rivedi le regole VCL perché troppe richieste passano al backend.

Il comando varnishlog mostra log dettagliati per ogni richiesta, che sono inestimabili per il debug del motivo per cui specifiche richieste non vengono cachate. Puoi filtrare per pattern URL, codice di risposta o stato di cache hit/miss.

Il comando varnishtop mostra una lista classificata delle voci di log più frequenti, aiutandoti a identificare pattern nei cache miss o negli errori.

Errori comuni

Dimenticare di rimuovere i cookie

La configurazione errata più comune di Varnish con PrestaShop è non rimuovere i cookie di analytics e tracciamento. Questi cookie sono presenti in praticamente ogni richiesta e rendono ogni richiesta unica dal punto di vista di Varnish, risultando in un tasso di hit dello 0%. Rimuovi sempre i cookie che non ti servono per la variazione della cache.

Cachare contenuto personalizzato

Se il tuo VCL è troppo aggressivo, cacherà pagine che contengono contenuto personalizzato (saluto dell'utente loggato, contenuto del carrello) e le servirà ad altri visitatori. Questo causa seri problemi di usabilità e potenziali problemi di privacy. Passa sempre le richieste che contengono cookie di sessione al backend.

Non invalidare ai cambi di contenuto

Senza un meccanismo di purging adeguato, le modifiche al contenuto nel back office non saranno visibili fino alla scadenza naturale delle pagine cachate. Per un negozio con cambiamenti attivi dell'inventario, questo significa che i visitatori potrebbero vedere prodotti esauriti, prezzi sbagliati o descrizioni obsolete. Implementa il supporto PURGE o BAN e integralo con gli hook di aggiornamento di PrestaShop.

Ignorare HTTPS

Varnish non gestisce SSL nativamente. Devi mettere un proxy di terminazione SSL (Nginx, HAProxy o un load balancer cloud) davanti a Varnish. Non pianificare questo nella tua architettura porta a problemi di contenuto misto (mixed content), loop di redirect o l'impossibilità di servire traffico HTTPS.

Varnish è adatto al tuo negozio?

Varnish è uno strumento potente, ma non è la scelta giusta per ogni negozio PrestaShop. Aggiunge complessità operativa: un altro servizio da monitorare, un altro linguaggio di configurazione da imparare, un altro livello nel tuo processo di debug. I benefici sono chiari e misurabili per i negozi che ne hanno bisogno, ma comportano un costo in termini di tempo di setup, manutenzione e difficoltà di troubleshooting.

Se il tuo negozio serve meno di 50.000 visualizzazioni di pagina al giorno e il tuo server gestisce il carico comodamente con un modulo FPC, Varnish è complessità non necessaria. Se il tuo negozio affronta regolarmente picchi di traffico che sovraccaricano il server, serve un alto volume di traffico di navigazione anonima o necessita dei tempi di risposta più rapidi possibili per SEO o esperienza utente, Varnish fornisce un livello di prestazioni che nessuna soluzione di caching basata su PHP può eguagliare.

Inizia con una corretta ottimizzazione di PrestaShop (ottimizzazione delle query, audit dei moduli, PHP OPcache, ottimizzazione delle immagini) e un modulo FPC. Se queste ottimizzazioni non bastano, Varnish è il passo successivo nella scala del performance scaling.

Questa risposta ti è stata utile?

Hai ancora domande?

Can't find what you're looking for? Send us your question and we'll get back to you quickly.

Loading...
Back to top