Estoy almacenando en caché páginas generadas dinámicamente (PHP-FPM, NGINX) y tengo barniz frente a ellas, esto funciona muy bien.
Sin embargo, una vez que se alcanza el tiempo de espera de caché, veo esto:
- nueva página de solicitudes de clientes
- barniz reconoce el tiempo de espera de caché
- el cliente espera
- el barniz obtiene una nueva página del backend
- barniz entrega una nueva página al cliente (y también tiene una página en caché para la siguiente solicitud que la obtiene al instante)
Lo que me gustaría hacer es:
- página de solicitudes del cliente
- el barniz reconoce el tiempo de espera
- barniz entrega la página anterior al cliente
- barniz obtiene una nueva página del backend y la coloca en la memoria caché
En mi caso, no es un sitio donde la información desactualizada es un problema tan grande, especialmente cuando hablamos del tiempo de espera de caché de unos pocos minutos.
Sin embargo, no quiero que el usuario castigado espere en la cola y entregue algo inmediato. ¿Es eso posible de alguna manera?
Para ilustrar, aquí hay una salida de muestra de ejecutar asedio 5 minutos contra mi servidor que se configuró para almacenar en caché durante 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
...
Dejé fuera los cientos de solicitudes que se ejecutaban más 0.02
o menos. Pero todavía me preocupa que haya usuarios que tengan que esperar casi 2 segundos para su HTML sin formato.
¿No podemos hacer algo mejor aquí?
(Me encontré con el envío de Varnish mientras estaba en caché , sonaba similar pero no exactamente lo que estoy tratando de hacer).
Solución
La respuesta de Shane Madden contenía la solución, pero no me di cuenta de inmediato. Hubo otro detalle que no incluí en mi pregunta porque pensé que no era relevante, pero en realidad lo es.
La solución CMS que estoy usando actualmente tiene una base de datos de barniz y, por lo tanto, tiene la capacidad de notificar a barniz para prohibir las páginas cuyo contenido ha cambiado. Envió una PURGE
solicitud con algunas expresiones regulares para prohibir ciertas páginas.
Para resumir, hay dos casos en los que tuve usuarios desafortunados:
- el barniz normal TTL de una página caduca
- los usuarios del backend cambian de contenido, esto envía una solicitud de purga al barniz
En ambos casos tengo usuarios "desafortunados". En el segundo caso, se alivia por el hecho de que los usuarios del backend generalmente revisan la página después de que se ha cambiado; pero no necesariamente
Sin embargo, para el segundo caso, creé una solución (sí, me doy cuenta de que esta pregunta comenzó buscando una respuesta para el primer caso ... pregunta mal formulada de mi parte):
En lugar de enviar una solicitud de purga, utilicé la sugerencia de Shanes y ajusté el VCL para que mi escucha de la base de datos de barniz pueda enviar una solicitud especial para buscar una página con hash_always_miss
set to true
.
Con la arquitectura actual, realmente no tengo el lujo de hacer una solicitud asincrónica real, pero con la ayuda de ¿Cómo hago una solicitud GET asincrónica en PHP? Pude elaborar una solicitud GET para barnizar que no espera a que se cargue la página, pero es lo suficientemente buena como para activar el barniz para recuperar la página del back-end y almacenarla en caché.
El efecto neto fue que el oyente de la base de datos envió la solicitud al barniz y, mientras estaba sondeando la página específica, nunca hizo que mis solicitudes fueran "desafortunadas", pero una vez que el barniz recuperó la página completamente desde el backend (esto puede variar de 300 ms a 2 segundos) De repente estaba allí.
Todavía tengo que encontrar una solución para evitar los mismos problemas cuando se agota el TTL normal, pero supongo que la solución también es exactamente como sugiere Shane: usando wget para desencadenar hash_always_miss
, tendré que ser lo suficientemente inteligente como para obtener la lista de páginas que tengo que actualizar.
fuente
@EDITAR:
Solo una pregunta rápida para hacerle saber que esta característica parece haberse implementado en la última versión en la rama maestra, es probable que su versión no admita una verdadera revalidación aún obsoleta / el ejemplo que publiqué serviría Las solicitudes 9999/10000 con un bugger pobre todavía tienen que esperar a que se complete la solicitud en el back-end (Aún mejor que nada;) ...
Bueno, no estoy 100% seguro de por qué los comentarios anteriores dicen que no está funcionando, pero de acuerdo con: https://www.varnish-software.com/static/book/Saving_a_request.html
Actualmente estoy usando la configuración como dice el manual y está funcionando bien ... Aquí hay un fragmento de mi archivo vcl ...
Tenga en cuenta que si desea proporcionar un período de gracia de respuesta de back-end más largo (para un error de 500 como en mi configuración) deberá configurar el sondeo de back-end ... Aquí hay una copia de mi sonda de back-end ...
fuente
En Varnish 3 esto se logra a través del "modo Grace". De acuerdo con el manual [1], debe agregar la siguiente lógica:
[1] https://www.varnish-cache.org/docs/3.0/tutorial/handling_misbehaving_servers.html#grace-mode
fuente