Solicita que a força perca o cache, mas ainda armazene a resposta

7

Eu tenho um aplicativo da web lento no qual coloquei o Varnish na frente. Todas as páginas são estáticas (elas não variam para um usuário diferente), mas precisam ser atualizadas a cada 5 minutos para que contenham dados recentes.

Eu tenho um script simples ( wget --mirror ) que rastreia todo o site a cada 15 minutos. Cada rastreamento leva cerca de 5 minutos. O objetivo do rastreamento é atualizar todas as páginas do cache do Varnish para que o usuário nunca precise esperar que a página seja gerada (já que todas as páginas foram geradas recentemente graças ao spider).

A linha do tempo é assim:

  • 00:00:00: Cache liberado
  • 00:00:00: Spider começa a rastrear para atualizar o cache com novas páginas
  • 00:05:00: Spider termina de rastrear, todas as páginas são atualizadas até 00:15:00

Uma solicitação entre 0:00:00 e 0:05:00 pode atingir uma página que ainda não foi atualizada e será forçada a aguardar alguns segundos por uma resposta. Isso não é aceitável.

O que eu gostaria de fazer é, talvez, usar um pouco de magia VCL, sempre enviar solicitações do spider para o backend, mas ainda armazenar a resposta no cache. Desta forma, um usuário nunca terá que esperar por uma página para gerar uma vez que não há janela de 5 minutos em que partes do cache estão vazias (exceto talvez na inicialização do servidor).

Como posso fazer isso?

    
por Tom Marthenal 08.09.2012 / 07:53

2 respostas

10

req.hash_always_miss deve fazer o truque.

Não faça um cache completo no início da corrida de aranha. Em vez disso, basta configurar o spider para funcionar - e no seu vcl_recv , defina os pedidos do spider para sempre perder a consulta do cache; eles vão buscar uma nova cópia do backend.

acl spider {
  "127.0.0.1";
  /* or whereever the spider comes from */
}

sub vcl_recv {
  if (client.ip ~ spider) {
    set req.hash_always_miss = true;
  }
  /* ... and continue as normal with the rest of the config */
}

Enquanto isso está acontecendo e até que a nova resposta esteja no cache, os clientes continuarão a fornecer o cache mais antigo para eles (contanto que ele ainda esteja em seu TTL).

    
por 08.09.2012 / 08:27
2

A resposta de Shane acima é melhor que esta. Esta é uma solução alternativa que é mais complicada e tem problemas adicionais. Por favor, envie a resposta de Shane, não esta. Estou apenas mostrando outro método para resolver o problema.

Meu pensamento inicial foi return (pass); in vcl_recv e, depois que a solicitação foi buscada, em vcl_fetch , de alguma forma instruímos Varnish que deveria armazenar o objeto em cache, até mesmo foi especificamente passado anteriormente.

Acontece que isso não é possível :

If you chose to pass the request in an earlier VCL function (e.g.: vcl_recv), you will still execute the logic of vcl_fetch, but the object will not enter the cache even if you supply a cache time.

Assim, a próxima melhor coisa é acionar uma pesquisa como uma solicitação normal, mas certifique-se de que ela sempre falhe. Não há como influenciar o processo de busca, então ele sempre vai funcionar (assumindo que é armazenado em cache; se não estiver, ele vai perder e armazenar de qualquer maneira). Mas podemos influenciar vcl_hit :

sub vcl_hit {
    # is this our spider?
    if (req.http.user-agent ~ "Wget" && client.ip ~ spider) {
        # it's the spider, so purge the existing object
        set obj.ttl = 0s;
        return (restart);
    }

    return (deliver);
}

Não podemos forçar a não utilização do cache, mas podemos remover esse objeto do cache e reiniciar todo o processo. Agora ele volta ao começo, em vcl_recv , onde eventualmente faz outra pesquisa. Como removemos o objeto que estamos tentando atualizar, ele não será executado, buscaremos os dados e atualizaremos o cache.

Um pouco complicado, mas funciona. A única janela para um usuário ficar preso entre uma limpeza e a resposta que está sendo armazenada é o tempo para a única solicitação ser processada. Não é perfeito, mas é muito bom.

    
por 08.09.2012 / 08:49

Tags