Estou fazendo cache de páginas geradas dinamicamente (PHP-FPM, NGINX) e tenho verniz na frente deles, isso funciona muito bem.
No entanto, quando o tempo limite do cache é atingido, vejo isso:
- nova página de solicitações de clientes
- o verniz reconhece o tempo limite do cache
- cliente aguarda
- o verniz busca uma nova página do backend
- o verniz entrega uma nova página ao cliente (e também tem a página armazenada em cache para a próxima solicitação que obtém instantaneamente)
O que eu gostaria de fazer é:
- página de solicitações do cliente
- o verniz reconhece o tempo limite
- o verniz entrega a página antiga ao cliente
- o verniz obtém uma nova página do backend e a coloca no cache
No meu caso, não é um site onde informações desatualizadas são um problema tão grande, especialmente quando falamos de um tempo limite de cache de alguns minutos.
No entanto, não quero punir o usuário para esperar na fila e sim entregar algo imediato. Isso é possível de alguma forma?
Para ilustrar, aqui está um exemplo de execução de cerco de 5 minutos contra o meu servidor que foi configurado para armazenar em cache por um 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
...
Deixei de fora as centenas de solicitações em execução em 0.02
ou mais. Mas ainda me preocupa que haverá usuários tendo que esperar quase 2 segundos pelo seu HTML bruto.
Não podemos fazer melhor aqui?
(deparei-me com Envnish send while cache , parecia semelhante, mas não exatamente o que eu estou tentando fazer.)
Solução
A resposta de Shane Madden continha a solução, mas eu não percebi imediatamente. Houve outro detalhe que não incluí na minha pergunta porque achei que não era relevante, mas na verdade é.
A solução CMS que estou usando atualmente tem um ouvinte de banco de dados de verniz e, portanto, tem a capacidade de notificar o verniz para banir páginas cujo conteúdo foi alterado. Enviou uma solicitação PURGE
com algum regex para banir certas páginas.
Para resumir as coisas, há dois casos em que eu tive usuários sem sorte:
- o verniz normal TTL de uma página expira
- usuários de back-end alteram o conteúdo, isso envia uma solicitação de exclusão para o verniz
Em ambos os casos, estou tendo usuários "sem sorte". No segundo caso, é aliviado pelo fato de que os usuários de back-end geralmente verificam a página depois que ela foi alterada; mas não necessariamente.
No entanto, para o segundo caso, criei uma solução (sim, percebo que essa pergunta começou com a busca de uma resposta para o primeiro caso ... pergunta mal formulada de minha parte):
Em vez de enviar uma solicitação de limpeza, usei a sugestão de Shanes e ajustei a VCL para que meu ouvinte do banco de dados de verniz pudesse enviar uma solicitação especial para buscar uma página com hash_always_miss
definido como true
.
Com a arquitetura atual, não tenho realmente o luxo de fazer uma solicitação assíncrona real, mas com a ajuda de Como faço para fazer uma requisição GET assíncrona em PHP? Eu consegui criar uma requisição GET para verniz que não espera que a página seja carregada, mas é boa o suficiente para acionar o verniz para buscar a página do backend e armazená-la em cache.
O efeito líquido foi que o ouvinte do banco de dados enviou a solicitação para o verniz e enquanto eu estava pesquisando a página específica, ela nunca tornava meus pedidos "azarados", mas uma vez que o verniz buscava a página completamente (isso pode variar de 300 ms a 2s) de repente estava lá.
Eu ainda tenho que encontrar uma solução para evitar os mesmos problemas quando o TTL normal se esgota, mas eu acho que a solução também é exatamente como Shane sugere: usar o wget para acionar o hash_always_miss
, eu vou ter que seja esperto o suficiente para obter uma lista de páginas que eu tenho que atualizar.