Je mets en cache des pages générées dynamiquement (PHP-FPM, NGINX) et j'ai du vernis devant elles, cela fonctionne très bien.
Cependant, une fois le délai d'expiration du cache atteint, je vois ceci:
- page des nouvelles demandes des clients
- le vernis reconnaît le délai d'expiration du cache
- le client attend
- le vernis récupère une nouvelle page depuis le backend
- le vernis fournit une nouvelle page au client (et a également mis en cache la page pour la prochaine demande qui l'obtient instantanément)
Ce que je voudrais faire, c'est:
- page des demandes des clients
- le vernis reconnaît le délai d'attente
- le vernis remet l'ancienne page au client
- le vernis récupère la nouvelle page du backend et la place dans le cache
Dans mon cas, ce n'est pas un site où les informations obsolètes sont un gros problème, surtout pas lorsque nous parlons d'un délai d'expiration du cache de quelques minutes.
Cependant, je ne veux pas punir l'utilisateur pour faire la queue et plutôt livrer quelque chose immédiatement. Est-ce possible d'une manière ou d'une autre?
Pour illustrer, voici un exemple de sortie de siège en cours d'exécution 5 minutes contre mon serveur qui a été configuré pour mettre en cache pendant une minute:
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
...
J'ai laissé de côté les centaines de demandes en cours 0.02
. Mais cela m'inquiète toujours qu'il y aura des utilisateurs qui devront attendre près de 2 secondes pour leur HTML brut.
Ne pouvons-nous pas faire mieux ici?
(Je suis tombé sur l' envoi de vernis lors de la mise en cache , cela semblait similaire, mais pas exactement ce que j'essaie de faire.)
Solution
La réponse de Shane Madden contenait la solution mais je ne l'ai pas réalisée tout de suite. Il y avait un autre détail que je n'ai pas inclus dans ma question parce que je pensais que ce n'était pas pertinent, mais en fait il l'est.
La solution CMS que j'utilise actuellement dispose d'un écouteur de base de données de vernis et a donc la capacité de notifier le vernis pour interdire les pages dont le contenu a changé. Il a envoyé une PURGE
demande avec quelques regex pour interdire certaines pages.
Pour résumer, il y a deux cas où j'ai eu des utilisateurs malchanceux:
- le vernis TTL normal d'une page expire
- les utilisateurs du backend modifient le contenu, cela envoie une demande de purge au vernis
Dans les deux cas, j'ai des utilisateurs "malchanceux". Dans le second cas, il est atténué par le fait que les utilisateurs du backend vérifient généralement la page après l'avoir modifiée; mais pas nécessairement.
Néanmoins, pour le deuxième cas j'ai créé une solution (oui, je me rends compte que cette question a commencé par chercher une réponse pour le premier cas ... question mal formulée de ma part):
Au lieu d'envoyer une demande de purge, j'ai utilisé la suggestion de Shanes et ajusté la VCL pour que mon écouteur de base de données de vernis puisse envoyer une demande spéciale pour récupérer une page avec hash_always_miss
set to true
.
Avec l'architecture actuelle, je n'ai pas vraiment le luxe de faire une vraie demande asynchrone, mais avec l'aide de Comment faire une demande GET asynchrone en PHP? J'ai pu créer une demande GET pour vernir qui n'attend pas que la page soit chargée mais est assez bonne pour déclencher le vernis pour récupérer la page du backend et la mettre en cache.
L'effet net a été que l'écouteur de la base de données a envoyé la demande au vernis et pendant que je sondais la page spécifique, il n'a jamais fait de demandes "malchanceuses" mais une fois que le vernis a récupéré la page complètement depuis le backend (cela peut aller de 300 ms à 2 s), il était soudainement là.
Je dois encore trouver une solution pour éviter les mêmes problèmes lorsque le TTL normal s'épuise, mais je suppose que la solution est également exactement comme Shane le suggère: en utilisant wget pour déclencher le hash_always_miss
, je devrai être assez intelligent pour obtenir la liste de pages que je dois rafraîchir.
la source
@ÉDITER:
Juste un petit rapide pour vous faire savoir que cette fonctionnalité ne semble avoir été implémentée que dans la dernière version de la branche principale, il y a de fortes chances que votre version ne prenne pas encore en charge le vrai périmé pendant la revalidation / l'exemple que j'ai publié servirait 9999/10000 requêtes avec un pauvre bugger devant encore attendre la fin de la requête en backend (Encore mieux que rien;) ...
Eh bien, je ne suis pas sûr à 100% pourquoi les commentaires précédents disent que cela ne fonctionne pas, mais selon: https://www.varnish-software.com/static/book/Saving_a_request.html
J'utilise actuellement une configuration comme ce que dit le manuel et ça fonctionne bien ... Voici un extrait de mon fichier vcl ...
Notez que si vous souhaitez fournir un temps de grâce de réponse plus long (pour une erreur de 500 comme dans ma configuration), vous devrez configurer la vérification du backend ... Voici une copie de ma sonde du backend ..
la source
Dans Varnish 3, ceci est réalisé via le "mode Grace". Selon le manuel [1], vous devez ajouter la logique suivante:
[1] https://www.varnish-cache.org/docs/3.0/tutorial/handling_misbehaving_servers.html#grace-mode
la source