20 Ottobre 2022

Intestazioni della Cache HTTP

Best Practices per la gestione della cache delle risorse statiche e l’utilizzo delle intestazioni della cache corrette come Cache-Control.

Esistono molte intestazioni HTTP diverse che possono essere utilizzate dal tuo sito web. In questo momento, ci concentreremo su un sottoinsieme specifico di questi: le intestazioni della cache. Ti mostreremo i dettagli quando si tratta di intestazioni della cache, quindi in futuro saprai come usarle!

Nel contesto di siti Web e app, la memorizzazione nella cache è definita come la memorizzazione del contenuto in una memoria temporanea, come quella sul browser o sul dispositivo dell’utente o su un server intermedio, per ridurre il tempo necessario per accedere a quel file.

Secondo HTTP Archive, tra i primi 300.000 siti, il browser dell’utente può memorizzare nella cache quasi la metà di tutto il contenuto scaricato.

Riduce il tempo necessario all’utente per visualizzare le immagini oi file Javascript o CSS. Questo perché l’utente ora accede al file dal suo sistema invece di essere scaricato dalla rete. Allo stesso tempo, la memorizzazione nella cache riduce anche il numero di richieste e il trasferimento di dati dai tuoi server. Indubbiamente questo è un enorme risparmio per le visualizzazioni e le visite ripetute di pagina.

Come funziona la memorizzazione nella cache?

Supponiamo di aprire una pagina web https://www.example.com e che il server restituisca il seguente codice HTML:

...
<link type="text/css" href="https://www.example.com/app.css" rel="stylesheet">
...
<!-- Rest of the HTML -->

Quando il browser analizza questo codice HTML, identifica che una risorsa CSS deve essere caricata da https://www.example.com/app.css .

Il browser invia una richiesta al server per questo file, il server restituisce il file e dice anche al browser di memorizzarlo nella cache per 30 giorni. Più avanti in questa guida, tratteremo come il server invia queste istruzioni al browser.

OTTIENI app.css, nessun oggetto trovato nella cache locale

Ora, supponiamo che tu apra un’altra pagina sullo stesso sito Web dopo alcune ore. Il browser analizza nuovamente l’HTML e trova lo stesso file CSS anche in questa pagina: https://www.example.com/app.css . Poiché il browser ha questa particolare risorsa disponibile nella sua cache locale, non andrà nemmeno al server. La richiesta di rete non viene mai effettuata, si accede al file dalla cache locale e gli stili vengono applicati molto rapidamente.

Come si realizza?

Esiste una gamma di intestazioni di cache e relative direttive che forniscono istruzioni esplicite a qualsiasi server, CDN e browser dell’utente finale su come gestire il contenuto in termini di cache. La combinazione di più funzionalità può darti i risultati desiderati o potrebbero causare il mancato funzionamento della cache perché vengono utilizzate in modo errato. Ti forniremo una rapida panoramica delle intestazioni della cache HTTP più comuni , delle loro direttive e di come utilizzarle.

Cache-Control: direttive

Esistono più direttive che possono essere utilizzate per controllare la funzionalità delle intestazioni della cache. Non devi usarli tutti, quindi scegli quelli che ti servono e lascia fuori gli altri. Queste sono le direttive più importanti:

max-age

Nella maggior parte degli usi delle intestazioni di controllo della cache vedrai questa direttiva in uso. Indica la quantità di tempo massima in secondi in cui le risposte recuperate possono essere riutilizzate dal momento in cui viene effettuata una richiesta. Ad esempio: max-age=300indica che una risorsa può essere riutilizzata per i successivi 300 secondi. Questa risorsa può essere memorizzata nella cache dal browser o da qualsiasi cache a valle del server per questo periodo di tempo.

s-maxage

Il s-prefisso “ ” sta per condiviso come nella cache condivisa. Questa direttiva è esplicitamente per CDN tra le altre cache intermedie. Questa direttiva sovrascrive la max-agedirettiva e fa scadere il campo di intestazione quando presente. È importante ricordare che questa direttiva non influirà sui browser dei visitatori. Quindi puoi utilizzare valori diversi per mag-ages-maxagespecificare tempi di cache diversi sia per i visitatori che per i CDN.

Può essere utile, ad esempio qualora utilizziate sistemi di cache come Varnish e vogliate istruire il server cache a settare un determinato tempo di cache alcune pagine.

no-cache

La no-cachedirettiva mostra che le risposte restituite non possono essere utilizzate per richieste successive allo stesso URL prima di verificare se le risposte del server sono state modificate. Con un ETag appropriato (noto anche come token di convalida) presente, di conseguenza, si verifica no-cacheun roundtrip nel tentativo di convalidare le risposte memorizzate nella cache. Le cache possono tuttavia eliminare i download se le risorse non sono cambiate. Ciò significa che i browser Web potrebbero memorizzare nella cache gli asset ma devono controllare ogni richiesta se gli asset sono cambiati (il server restituirà una risposta HTTP 304 se non è cambiato nulla).

no-store

Diversamente da no-cache, la no-storedirettiva è più semplice. Questo perché impedisce ai browser e a tutte le cache intermedie di archiviare qualsiasi versione delle risposte restituite, ad esempio risposte contenenti informazioni private/personali o dati bancari. Ogni volta che gli utenti richiedono questo asset, le richieste vengono inviate al server. Le risorse vengono scaricate ogni volta.

public

Se una risposta è contrassegnata come pubblica, può essere memorizzata nella cache anche nei casi in cui è associata a un’autenticazione HTTP o il codice di stato della risposta HTTP non è normalmente memorizzabile nella cache. Poiché le informazioni esplicite sulla memorizzazione nella cache, ad esempio tramite la max-agedirettiva, mostrano che una risposta è comunque memorizzabile nella cache, l’utilizzo di questa direttiva di solito non è necessario.

Nella maggior parte dei casi, una risposta contrassegnata come public non è necessaria, poiché le informazioni di memorizzazione nella cache esplicite (ad es. max-age) mostrano che una risposta è comunque memorizzabile nella cache.

private

Una risposta contrassegnata come privata può essere memorizzata nella cache dal browser. Tuttavia, queste risposte sono generalmente destinate a utenti singoli, quindi non sono memorizzabili nella cache da cache intermedie (ad es. pagine HTML con informazioni utente private possono essere memorizzate nella cache dal browser di un utente ma non da una CDN).

expires

Tempo fa questa intestazione veniva utilizzata per sfruttare i meccanismi di memorizzazione nella cache. Questa intestazione contiene semplicemente un contrassegno di data e ora. È ancora utile per i vecchi programmi utente, ma è importante notare che le intestazioni Cache-Control max-agehanno s-maxageancora la precedenza sulla maggior parte dei sistemi moderni.

last-modified

Questa intestazione è uno dei validatori più comuni per la cache. Indica quando una risorsa richiesta è stata modificata l’ultima volta. Anche se è uno dei validatori più comuni, le sue origini risalgono all’era HTTP/1.0, rendendolo visto da alcuni come un validatore legacy.

Etag

Un metodo di convalida più recente è l’utilizzo di ETag. Questo è diventato lo standard da HTTP/1.1. Questo viene convalidato tramite un campo di intestazione ETag. Di solito si basa su un hash del contenuto richiesto, ma non deve essere così. Tuttavia, il client che lo richiede non deve avere alcuna conoscenza di come viene generato. Se un client ha un oggetto nella sua cache che è scaduto, può utilizzare l’ETag per inviare una richiesta HTTP al server. Il server verificherà quindi questo token rispetto alle risorse memorizzate nella cache. Se l’asset non è stato modificato, il server può restituire una risposta 304 non modificata al client. Ciò rigenererà la durata della risorsa memorizzata nella cache, invece di riscaricare la risorsa.

Etag può essere un header di convalida sostitutivo o complementare a last-modified. Può essere particolarmente utile implementarlo quando si ha a che fare con intestazioni last-modified errate o si ha la necessità di disabilitarle rimuovendo l’header.

Vediamo dei casi pratici

Qualsiasi tipo di memorizzazione nella cache normalmente funzionerebbe attraverso l’aggiornamento e la convalida. Spieghiamo cosa significa. Le nuove richieste in genere ti daranno una nuova copia del contenuto servito istantaneamente dalla cache. Tuttavia, una rappresentazione convalidata raramente invierà di nuovo l’intera copia se non è cambiata dall’ultima volta che l’hai richiesta. Nei casi in cui non è presente alcun validatore (ad esempio un ETag o un’intestazione Last-Modified) combinato con una mancanza di informazioni sulla freschezza, di solito sarà considerato non memorizzabile nella cache.

Ottenere la corretta memorizzazione nella cache offre enormi vantaggi in termini di prestazioni, consente di risparmiare larghezza di banda e riduce i costi del server, ma molti siti utilizzano metà della memorizzazione nella cache, creando condizioni di competizione con conseguente perdita di sincronizzazione delle risorse interdipendenti.

La stragrande maggioranza della memorizzazione nella cache delle migliori pratiche rientra in uno dei due modelli seguenti:

Schema 1: contenuto immutabile + max-age

Cache-Control: max-age=31536000
  • Il contenuto di questo URL non cambia mai, quindi…
  • Il browser/CDN può memorizzare nella cache questa risorsa per un anno senza problemi
  • Il contenuto memorizzato nella cache di meno di max-agesecondi può essere utilizzato senza consultare il server

In questo modello, non modifichi mai il contenuto in un determinato URL, cambi l’URL:

<script src="/script-f93bca2c.js"></script>
<link rel="stylesheet" href="/styles-a837cb1e.css" />
<img src="/cats-0e9a2ef4.jpg" alt="" />

Ogni URL contiene qualcosa che cambia insieme al suo contenuto. Potrebbe essere un numero di versione, la data di modifica o un hash del contenuto, che è quello che faccio su questo blog.

Tuttavia, questo modello non funziona per cose come articoli e post di blog. I loro URL non possono essere versionati e il loro contenuto deve poter cambiare. Seriamente, dati gli errori di ortografia e grammatica di base che commetto, devo essere in grado di aggiornare i contenuti in modo rapido e frequente.

Schema 2: contenuto modificabile, sempre riconvalidato dal server

Cache-Control: no-cache
  • Il contenuto di questo URL potrebbe cambiare, quindi…
  • Qualsiasi versione memorizzata nella cache locale non è attendibile senza l’autorizzazione del server

Nota: no-cache non significa “non memorizzare nella cache”, significa che deve controllare (o “riconvalidare” come lo chiama) con il server prima di utilizzare la risorsa memorizzata nella cache. no-storedice al browser di non memorizzarlo affatto nella cache. Inoltre must-revalidatenon significa “deve rivalidare”, significa che la risorsa locale può essere utilizzata se è più giovane di quella fornita max-age, altrimenti deve essere riconvalidata. Sì. Lo so.

In questo modello puoi aggiungere un’intestazione ETag(un ID versione a tua scelta) o una Last-Modifieddata alla risposta. La prossima volta che il client recupera la risorsa, fa eco al valore per il contenuto che ha già tramite If-None-MatchIf-Modified-Sincerispettivamente, consentendo al server di dire “Usa solo ciò che hai già, è aggiornato” o come si scrive ” HTTP 304″.

Se l’invio ETagLast-Modifiednon è possibile, il server invia sempre l’intero contenuto.

Questo modello comporta sempre un recupero della rete, quindi non è buono come il modello 1 che può bypassare completamente la rete.

Non è raro essere scoraggiati dall’infrastruttura necessaria per il modello 1, ma allo stesso modo essere scoraggiati dalla richiesta di rete richiesta dal modello 2 e invece scegliere qualcosa nel mezzo: un max-agecontenuto piccolo e mutevole. Questo è un bel compromesso.

max-age su contenuti mutevoli è spesso la scelta sbagliata

…e sfortunatamente non è raro, ad esempio accade sulle pagine di Github.

Immaginare:

  • /article/
  • /styles.css
  • /script.js

…il tutto servito con:

Cache-Control: deve essere riconvalidato, max-age=600
  • Il contenuto degli URL cambia
  • Se il browser ha una versione memorizzata nella cache di meno di 10 minuti, usala senza consultare il server
  • In caso contrario, effettuare un recupero di rete, utilizzando If-Modified-SinceIf-None-Matchse disponibile

Questo modello può sembrare funzionare durante i test, ma rompe le cose nel mondo reale ed è davvero difficile da rintracciare. Nell’esempio sopra, il server aveva effettivamente aggiornato HTML, CSS e JS, ma la pagina ha finito con il vecchio HTML e JS dalla cache e il CSS aggiornato dal server. La mancata corrispondenza della versione ha rotto le cose.

Spesso, quando apportiamo modifiche significative all’HTML, è probabile che modifichiamo anche il CSS per riflettere la nuova struttura e aggiorniamo il JS per soddisfare le modifiche allo stile e al contenuto. Queste risorse sono interdipendenti, ma le intestazioni di memorizzazione nella cache non possono esprimerlo. Gli utenti potrebbero ritrovarsi con la nuova versione di una/due delle risorse, ma la vecchia versione dell’altra/e.

max-ageè relativo al tempo di risposta, quindi se tutte le risorse di cui sopra sono richieste come parte della stessa navigazione verranno impostate per scadere più o meno alla stessa ora, ma c’è ancora la piccola possibilità di una gara lì. Se disponi di alcune pagine che non includono JS o includono CSS diversi, le date di scadenza potrebbero non essere sincronizzate. E peggio, il browser elimina continuamente le cose dalla cache e non sa che HTML, CSS e JS sono interdipendenti, quindi rilascerà felicemente uno ma non gli altri. Moltiplica tutto questo insieme e non è improbabile che tu possa ritrovarti con versioni non corrispondenti di queste risorse.

Per l’utente, ciò può causare layout e/o funzionalità interrotti. Da piccoli difetti a contenuti del tutto inutilizzabili.

Hai dei dubbi? Non sai da dove iniziare? Contattaci !

Abbiamo tutte le risposte alle tue domande per aiutarti nella giusta scelta.

Chatta con noi

Chatta direttamente con il nostro supporto prevendita.

0256569681

Contattaci telefonicamente negli orari d’ufficio 9:30 – 19:30

Contattaci online

Apri una richiesta direttamente nell’area dei contatti.

INFORMAZIONI

Managed Server S.r.l. è un player italiano di riferimento nel fornire soluzioni avanzate di sistemistica GNU/Linux orientate all’alta performance. Con un modello di sottoscrizione dai costi contenuti e prevedibili, ci assicuriamo che i nostri clienti abbiano accesso a tecnologie avanzate nel campo dell’hosting, server dedicati e servizi cloud. Oltre a questo, offriamo consulenza sistemistica su sistemi Linux e manutenzione specializzata in DBMS, IT Security, Cloud e molto altro. Ci distinguiamo per l’expertise in hosting di primari CMS Open Source come WordPress, WooCommerce, Drupal, Prestashop, Joomla, OpenCart e Magento, affiancato da un servizio di supporto e consulenza di alto livello adatto per la Pubblica Amministrazione, PMI, ed aziende di qualsiasi dimensione.

Red Hat, Inc. detiene i diritti su Red Hat®, RHEL®, RedHat Linux®, e CentOS®; AlmaLinux™ è un marchio di AlmaLinux OS Foundation; Rocky Linux® è un marchio registrato di Rocky Linux Foundation; SUSE® è un marchio registrato di SUSE LLC; Canonical Ltd. detiene i diritti su Ubuntu®; Software in the Public Interest, Inc. detiene i diritti su Debian®; Linus Torvalds detiene i diritti su Linux®; FreeBSD® è un marchio registrato di The FreeBSD Foundation; NetBSD® è un marchio registrato di The NetBSD Foundation; OpenBSD® è un marchio registrato di Theo de Raadt. Oracle Corporation detiene i diritti su Oracle®, MySQL®, e MyRocks®; Percona® è un marchio registrato di Percona LLC; MariaDB® è un marchio registrato di MariaDB Corporation Ab; REDIS® è un marchio registrato di Redis Labs Ltd. F5 Networks, Inc. detiene i diritti su NGINX® e NGINX Plus®; Varnish® è un marchio registrato di Varnish Software AB. Adobe Inc. detiene i diritti su Magento®; PrestaShop® è un marchio registrato di PrestaShop SA; OpenCart® è un marchio registrato di OpenCart Limited. Automattic Inc. detiene i diritti su WordPress®, WooCommerce®, e JetPack®; Open Source Matters, Inc. detiene i diritti su Joomla®; Dries Buytaert detiene i diritti su Drupal®. Amazon Web Services, Inc. detiene i diritti su AWS®; Google LLC detiene i diritti su Google Cloud™ e Chrome™; Microsoft Corporation detiene i diritti su Microsoft®, Azure®, e Internet Explorer®; Mozilla Foundation detiene i diritti su Firefox®. Apache® è un marchio registrato di The Apache Software Foundation; PHP® è un marchio registrato del PHP Group. CloudFlare® è un marchio registrato di Cloudflare, Inc.; NETSCOUT® è un marchio registrato di NETSCOUT Systems Inc.; ElasticSearch®, LogStash®, e Kibana® sono marchi registrati di Elastic N.V. Hetzner Online GmbH detiene i diritti su Hetzner®; OVHcloud è un marchio registrato di OVH Groupe SAS; cPanel®, L.L.C. detiene i diritti su cPanel®; Plesk® è un marchio registrato di Plesk International GmbH; Facebook, Inc. detiene i diritti su Facebook®. Questo sito non è affiliato, sponsorizzato o altrimenti associato a nessuna delle entità sopra menzionate e non rappresenta nessuna di queste entità in alcun modo. Tutti i diritti sui marchi e sui nomi di prodotto menzionati sono di proprietà dei rispettivi detentori di copyright. Ogni altro marchio citato appartiene ai propri registranti. MANAGED SERVER® è un marchio registrato a livello europeo da MANAGED SERVER SRL, Via Enzo Ferrari, 9, 62012 Civitanova Marche (MC), Italia.

SOLO UN ATTIMO !

Vorresti vedere come gira il tuo WooCommerce sui nostri sistemi senza dover migrare nulla ? 

Inserisci l'indirizzo del tuo sito WooCommerce e otterrai una dimostrazione navigabile, senza dover fare assolutamente nulla e completamente gratis.

No grazie, i miei clienti preferiscono il sito lento.
Torna in alto