Sto memorizzando nella cache pagine generate dinamicamente (PHP-FPM, NGINX) e ho una vernice davanti a loro, questo funziona molto bene.
Tuttavia, una volta raggiunto il timeout della cache, vedo questo:
- nuova pagina di richieste client
- varnish riconosce il timeout della cache
- il cliente aspetta
- la vernice recupera la nuova pagina dal backend
- varnish consegna una nuova pagina al client (e ha anche una pagina memorizzata nella cache per la prossima richiesta che la ottiene immediatamente)
Quello che vorrei fare è:
- pagina delle richieste del cliente
- la vernice riconosce il timeout
- La vernice consegna la vecchia pagina al client
- varnish recupera la nuova pagina dal backend e la inserisce nella cache
Nel mio caso non è un sito in cui le informazioni obsolete sono un problema così grande, soprattutto quando parliamo di timeout della cache da pochi minuti.
Tuttavia, non desidero punire l'utente in attesa in linea e piuttosto fornire qualcosa di immediato. È possibile in qualche modo?
Per illustrare, ecco un output di esempio di esecuzione dell'assedio 5 minuti sul mio server che è stato configurato per la cache per un minuto:
HTTP/1.1,200, 1.97, 12710,/,1,2013-06-24 00:21:06
...
HTTP/1.1,200, 1.88, 12710,/,1,2013-06-24 00:21:20
...
HTTP/1.1,200, 1.93, 12710,/,1,2013-06-24 00:22:08
...
HTTP/1.1,200, 1.89, 12710,/,1,2013-06-24 00:22:22
...
HTTP/1.1,200, 1.94, 12710,/,1,2013-06-24 00:23:10
...
HTTP/1.1,200, 1.91, 12709,/,1,2013-06-24 00:23:23
...
HTTP/1.1,200, 1.93, 12710,/,1,2013-06-24 00:24:12
...
Ho lasciato fuori le centinaia di richieste in esecuzione 0.02circa. Ma mi preoccupa ancora che ci saranno utenti che dovranno attendere quasi 2 secondi per il loro codice HTML non elaborato.
Non possiamo fare di meglio qui?
(Mi sono imbattuto in Varnish send mentre cache , sembrava simile ma non esattamente quello che sto cercando di fare.)
Soluzione
La risposta di Shane Madden conteneva la soluzione ma non me ne accorsi subito. C'era un altro dettaglio che non avevo incluso nella mia domanda perché pensavo non fosse rilevante, ma in realtà lo è.
La soluzione CMS che sto attualmente utilizzando ha un listener di database di vernici e quindi ha la capacità di notificare a vern per vietare le pagine il cui contenuto è cambiato. Ha inviato una PURGErichiesta con qualche regex per vietare determinate pagine.
Per riassumere, ci sono due casi in cui ho avuto utenti sfortunati:
- la vernice normale TTL di una pagina scade
- gli utenti backend cambiano contenuto, questo invia una richiesta di spurgo alla vernice
In entrambi i casi ho utenti "sfortunati". Nel secondo caso è alleviato dal fatto che gli utenti backend di solito controllano la pagina dopo che è stata modificata; ma non necessariamente.
Tuttavia, per il secondo caso ho creato una soluzione (sì, mi rendo conto che questa domanda è iniziata con la ricerca di una risposta per il primo caso ... domanda mal formulata da parte mia):
Invece di inviare una richiesta di eliminazione, ho usato il suggerimento di Shanes e ho modificato il VCL in modo che il mio listener di database di vernici possa inviare una richiesta speciale per recuperare una pagina con hash_always_missset su true.
Con l'architettura attuale non ho davvero il lusso di fare una vera richiesta asincrona, ma con l'aiuto di Come faccio a fare una richiesta GET asincrona in PHP? Sono stato in grado di creare una richiesta GET per la vernice che non aspetta il caricamento della pagina ma è abbastanza buona da innescare la vernice per recuperare la pagina dal back-end e memorizzarla nella cache.
L'effetto netto è stato che l'ascoltatore di database ha inviato la richiesta di vernice e mentre eseguivo il polling della pagina specifica non ha mai reso le mie richieste "sfortunate", ma una volta che la vernice ha recuperato la pagina completamente dal backend (questo può variare da 300 ms a 2 secondi) improvvisamente era lì.
Devo ancora trovare una soluzione su come evitare gli stessi problemi quando si esaurisce il normale TTL, ma immagino che la soluzione sia anche esattamente come suggerisce Shane: usando wget per innescare hash_always_miss, dovrò solo essere abbastanza intelligente per ottenere l'elenco di pagine che devo aggiornare.