Vale la pena cambiare l'intera struttura dei file delle immagini degli utenti per sfruttare la semplice memorizzazione nella cache del browser?


9

Su uno dei miei siti mobili, memorizzo semplicemente le immagini del profilo del mio utente come '1.jpg' nella loro cartella utente, e da lì procedo in modo incrementale per qualsiasi altra foto caricata. Ciò significa che ogni volta che cambiano la loro immagine del profilo, ad esempio, il nome del file rimane lo stesso.

Volevo approfittare della memorizzazione delle immagini nella cache in modo che la stessa vecchia foto non venga scaricata più volte ogni volta che il profilo di un utente viene visualizzato e rivisto, ma allo stesso tempo, voglio che i browser dei miei utenti scarica quello nuovo se è cambiato.

Da quello che ho letto, sembra che l'unico modo per farlo sia usare effettivamente nomi di file casuali e tenere traccia di tutti quei nomi di file nel DB, in modo da poter impostare una cache non in scadenza, mentre di recente le foto modificate vengono nuovamente estratte poiché hanno un nuovo nome file. Il bello del modo in cui li ho strutturati fino ad ora, tuttavia, è che posso saltare completamente il database e accedere ai file direttamente poiché la loro posizione è prevedibile.

Quindi la mia domanda è, vale la pena per me cambiare l'intera struttura dei file del mio sito, oltre ad aggiungere l'elemento DB, a beneficio della cache eterna e del nuovo download automatico al nuovo caricamento?

Questa è un'impresa enorme, ma se è considerata degna, non ho problemi ad andare avanti con questo drastico cambiamento. Voglio solo assicurarmi che questo sia il modo in cui i "ragazzi grandi" lo fanno in modo da non dover mai più cambiare la struttura dei file.

Grazie.

Risposte:


7

Una soluzione comunemente usata è quella di rendere gli URL delle immagini simili a questo:

http://www.example.com/path/to/images/1.jpg?v=123456

Qui /path/to/images/1.jpgè il percorso URL effettivo dell'immagine, mentre ?v=123456è solo una query fittizia fissata alla fine dell'URL. La stringa di query può essere qualsiasi cosa - un numero di versione, un timestamp, un hash del contenuto dell'immagine - purché lo modifichi ogni volta che l'immagine cambia e lo mantenga lo stesso quando non lo fa.

Il trucco è che il server Web, quando viene richiesto di fornire un tale URL, ignorerà la stringa di query, poiché l'URL in realtà punta a un file statico. Ma per il browser dell'utente (e per tutti i proxy in mezzo), gli URL con stringhe di query diverse saranno completamente diversi e quindi qualsiasi modifica alla stringa di query impone al browser di ricaricare il file.

Pertanto, è possibile configurare il server Web per l'invio Expirese Cache-Controlle intestazioni HTTP per consentire la memorizzazione nella cache indefinita, con la certezza che è possibile forzare un ricaricamento modificando la stringa di query. Un modo per farlo, se si utilizza Apache con mod_expires , è inserire un .htaccessfile nella directory delle immagini con le righe:

ExpiresActive On
ExpiresDefault "access plus 1 year"

Questa tecnica è utilizzata da molti siti Web popolari. Ad esempio, se guardi l'origine HTML di questa stessa pagina, scoprirai che il foglio di stile per esso è caricato da un URL come questo:

http://cdn.sstatic.net/stackoverflow/all.css?v=7cd8ea9d6f1e

Qui, ?v=7cd8ea9d6f1ec'è una stringa di query fittizia proprio come ho descritto sopra; puoi confermarlo cambiandolo e vedendo che in effetti restituisce comunque lo stesso file.


Anche interessante, ma come tenere traccia di quando il file è stato modificato l'ultima volta rispetto a quando il browser è stato visualizzato per la prima volta, al fine di determinare quando dovrei dire al browser dell'utente di recuperarlo di nuovo (ad esempio modificando il valore della query)?
ProgrammerGirl

1
Non è necessario tenere traccia della visualizzazione del file. Tieni semplicemente traccia dell'ultima modifica del file (o di qualche altra proprietà appropriata di esso) e includilo nella stringa di query. In questo modo, ogni volta che il file cambia, anche l'URL cambierà.
Ilmari Karonen,

Molto, molto, interessante. Quindi potrei presumibilmente recuperare la proprietà "ultima modifica" dei file e solo fare in modo che il valore della query sia corretto?
ProgrammerGirl

1
Sì, dovrebbe funzionare.
Ilmari Karonen,

1
Non ci sono aspetti negativi significativi di cui sono a conoscenza. Potresti finire con copie duplicate delle tue immagini negli indici dei motori di ricerca, ma almeno i principali motori di ricerca come Google sono piuttosto intelligenti nel gestire tali cose, dal momento che è un trucco così comune. In ogni caso, tale problema può essere mitigato inviando le intestazioni HTTP rel = "canonical" e mantenendo modesti i tempi di scadenza (diciamo, solo un mese o una settimana anziché un anno intero).
Ilmari Karonen,

6

C'è più di un modo per memorizzare nella cache.

Condizionale OTTENERE

Se stai memorizzando queste immagini sul file system e le stai servendo direttamente attraverso il web server, probabilmente stai già utilizzando get condizionale . Il server Web utilizzerà automaticamente i metadati del filesystem per impostare un'intestazione ETAG e risponderà automaticamente con "304 Not Modified" se il browser include If-Modified-Sinceo If-Matchesintestazioni nella sua richiesta. (Tutti i browser lo faranno.)

In questo caso l'intera immagine non viene restituita, quindi si ha un risparmio di larghezza di banda. Tuttavia, verrà comunque emessa una richiesta GET, quindi avrai comunque il sovraccarico e la latenza di una richiesta.

Puoi ridurre leggermente il numero di richieste a scapito della freschezza della cache facendo impostare al server web le Cache-Controlintestazioni con un public,max-age=Nvalore per le tue immagini. Ciò significa che le cache possono conservare la risorsa per un massimo di max-agesecondi prima che debbano verificare se è stata aggiornata.

Tuttavia, HTTP definisce solo un modo per invalidare una voce della cache, che potrebbe non adattarsi alla semantica della tua applicazione: se POST o PUT a un URL che aggiorna la foto del profilo, rispondi con Location: [url of photo]un'intestazione e la voce della cache per quell'URL verrà invalidata.

(Questo è il meccanismo che ti consente di memorizzare nella cache una pagina web con commenti e quindi ricaricare forzatamente la pagina dal browser dopo che l'utente ha pubblicato un nuovo commento. Il browser risponderebbe a POST /commentcon 303 See Othere a Location: /page/with/comment. Nota che questo non ha usato funzionare in Firefox a causa di un bug di vecchia data .)

A meno che tu non abbia molto traffico, questo approccio alla cache va bene.

Modifica degli URL

Un url è una rappresentazione di una risorsa, quindi un altro modo per gestire la memorizzazione nella cache non è modificare i parametri della cache per la risorsa, ma creare una nuova risorsa con una direttiva "cache per sempre". Questo è l'approccio che i "ragazzi grandi" prediligono, perché permette loro di non generare richieste extra, risparmiando loro molta larghezza di banda. Il rovescio della medaglia è che richiede molta più contabilità aggiuntiva.

Esistono due tecniche generali per questo.

Stringhe di query

I server Web ignorano le stringhe di query durante la pubblicazione di un file dal file system. Le cache, tuttavia, non lo fanno: /1.jpg?t=12345e /1.jpg?t=67890sono due risorse completamente diverse e non correlate, anche se il server pensa che siano le stesse.

Quindi una cosa semplice che puoi fare è aggiungere il timestamp del filesystem come stringa di query ogni volta che fai riferimento a una risorsa nel tuo html e imposti Expiresun'intestazione lunga . Il browser memorizzerà quindi questa risorsa per sempre e non eseguirà alcun GET purché la stringa di query non cambi.

Un aspetto negativo è che è difficile o impossibile istruire il server web del nuovo URL per un elemento se si desidera invalidare forzatamente una cache. Ad esempio, se un browser ha una pagina HTML memorizzata nella cache con un /1.jpg?v=1riferimento, ma /1.jpg?v=1è riuscito a cancellare la voce per (forse ha esaurito lo spazio di file o memoria), farà una nuova richiesta a /1.jpg?v=1. Se nel frattempo l'immagine è cambiata in /1.jpg?v=2, la risposta corretta è:

  1. Servire la vecchia versione del file. Lo faresti se volessi che tutte le risorse fossero coerenti tra loro come in un certo momento. Questo è ciò che dovresti fare con i file CSS, ad esempio, poiché un nuovo file CSS con un vecchio file html potrebbe non funzionare correttamente!
  2. Reindirizzare alla nuova versione del file utilizzando 301 Moved Permanently. Lo faresti se volessi che tutte le risorse siano le più nuove possibili.

Entrambi sono difficili da fare con un solo server web, il che significa che è necessario invocare un'applicazione Web anche per richieste di immagini, che può essere sia più complicata che più dispendiosa in termini di risorse. I server web sono molto veloci nel servire i file, quindi il sovraccarico di un'applicazione web potrebbe finire per inghiottire la tua larghezza di banda e i guadagni di latenza.

Nomi dei file

Invece di aggiungere una stringa di query, si modifica il nome file. Ciò significa che è facile mantenere più versioni dei file nel file system, ma probabilmente sarà necessario archiviare i metadati dei file e fare altri libri contabili per tenere traccia delle proprie risorse e dei loro nomi.


0

leggi lo stato http 304 Not Modified, dovresti essere in grado di rispondere a una richiesta di download con 304 e quindi dire al server di utilizzare i dati memorizzati nella cache, istintivamente di inviarli nuovamente al browser. e leggi questa domanda /programming/2978496/make-php-page-return-304-not-modified-if-it-hasnt-been-modified


Interessante, ma si tratta di una soluzione di "cerotto" a uno schema di file problematico o il mio schema di file è buono e necessita solo di questa capacità di memorizzazione nella cache? Inoltre, come faccio a sapere quando il file è stato modificato l'ultima volta rispetto a quando il browser è stato visualizzato per la prima volta, al fine di determinare quando dovrei dire al browser dell'utente di recuperarlo di nuovo?
ProgrammerGirl,

non mi è così familiare, penso che Francis Avila ne sappia molto di più
Puggan Se
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.