A proibição de verniz foi adicionada, mas o objeto antigo foi retornado

Jan 08 2021

Estou usando verniz na frente de um servidor de blocos para armazenar os blocos do mapbox. Para remover blocos antigos, eu pretendia usar proibições para remover efetivamente um grande número de blocos em cache. Meu problema é que o verniz ainda usa os objetos em cache (pelo menos o agena resposta indica isso) e não entra em contato com o backend.

Primeiro estou solicitando http: //varnish/5/3/4.pbf, depois adicionando um ban com curl -X BAN -H 'X-Purge-Regex: 5/3/4.pbf' varnishou alternativamente varnishadme, em ban obj.http.url ~ 5/3/4.pbfseguida, solicitando http: //varnish/5/3/4.pbf novamente.

No início, minha lista de banimentos está vazia:

Present bans:
1610117471.434488     1 C

O ban foi adicionado com sucesso com curl -X BAN -H 'X-Purge-Regex: 5/3/4.pbf' varnish

<!DOCTYPE html>
<html>
  <head>
    <title>200 Ban added</title>
  </head>
  <body>
    <h1>Error 200 Ban added</h1>
    <p>Ban added</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 8</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

e aparece na lista de banidos

Present bans:
1610117369.028870     0 -  obj.http.url ~ 5/3/4.pbf
1610117307.220739     1 C  

Depois de solicitar http: //varnish/5/3/4.pbf novamente, a lista de banimento indica que o banimento foi usado

Present bans:
1610117471.434488     1 -  obj.http.url ~ 5/3/4.pbf

mas a idade da resposta não é 0, porque ainda é o objeto da primeira solicitação.

Após um curto período de tempo, o banimento é removido:

Present bans:
1610117471.434488     1 C  

Minha vcl_recvaparência é assim, mas provavelmente o erro está em outro lugar, pois também não funciona com varnishadm:

sub vcl_recv {
    unset req.http.cookie;

    # Allowing PURGE from localhost
    if (req.method == "BAN"||req.method == "PURGE") {
                if (!client.ip ~ purge) {
                        return(synth(405,"Not allowed."));
                }
                if (req.method == "BAN") {
                    ban("obj.http.url ~ " + req.http.X-Purge-Regex);

                    # Throw a synthetic page so the
                    # request won't go to the backend.
                    return(synth(200, "Ban added"));
                }
                if (req.method == "PURGE") {
                    return (purge);
                }
        }
}

Eu também tentei usar o vcl_purgedehttps://stackoverflow.com/a/61507014 mas isso não parece ajudar nas proibições (?).

Estou usando o X-Purge-Regexcabeçalho para não me preocupar em ter que escapar caracteres especiais como emhttps://stackoverflow.com/a/38526921mas apenas uma proibição como obj.http.url ~ 0não funciona.

Estou usando verniz 6.5 com vcl 4.0.

Pedido de banimento

*   << Request  >> 54        
-   Begin          req 53 rxreq
-   Timestamp      Start: 1610121483.345437 0.000000 0.000000
-   Timestamp      Req: 1610121483.345437 0.000000 0.000000
-   VCL_use        boot
-   ReqStart       192.168.48.2 50882 http
-   ReqMethod      BAN
-   ReqURL         /
-   ReqProtocol    HTTP/1.1
-   ReqHeader      Host: varnish-volatile
-   ReqHeader      User-Agent: curl/7.64.0
-   ReqHeader      Accept: */*
-   ReqHeader      X-Purge-Regex: 0
-   ReqHeader      X-Forwarded-For: 192.168.48.2
-   VCL_call       RECV
-   VCL_acl        MATCH purge "importer"
-   VCL_return     synth
-   VCL_call       HASH
-   VCL_return     lookup
-   RespProtocol   HTTP/1.1
-   RespStatus     200
-   RespReason     Ban added
-   RespHeader     Date: Fri, 08 Jan 2021 15:58:03 GMT
-   RespHeader     Server: Varnish
-   RespHeader     X-Varnish: 54
-   VCL_call       SYNTH
-   RespHeader     Content-Type: text/html; charset=utf-8
-   RespHeader     Retry-After: 5
-   VCL_return     deliver
-   Timestamp      Process: 1610121483.347281 0.001844 0.001844
-   RespHeader     Content-Length: 246
-   Storage        malloc Transient
-   Filters        
-   RespHeader     Accept-Ranges: bytes
-   RespHeader     Connection: keep-alive
-   Timestamp      Resp: 1610121483.347557 0.002120 0.000276
-   ReqAcct        98 0 98 218 246 464
-   End            

OBTER após adicionar proibição

*   << Request  >> 32806     
-   Begin          req 32805 rxreq
-   Timestamp      Start: 1610121552.733872 0.000000 0.000000
-   Timestamp      Req: 1610121552.733872 0.000000 0.000000
-   VCL_use        boot
-   ReqStart       192.168.48.1 55176 http
-   ReqMethod      GET
-   ReqURL         /public.snow_db/0/0/0.pbf
-   ReqProtocol    HTTP/1.1
-   ReqHeader      Host: localhost:8090
-   ReqHeader      User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:84.0) Gecko/20100101 Firefox/84.0
-   ReqHeader      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
-   ReqHeader      Accept-Language: en-US,en;q=0.5
-   ReqHeader      Accept-Encoding: gzip, deflate
-   ReqHeader      DNT: 1
-   ReqHeader      Connection: keep-alive
-   ReqHeader      Upgrade-Insecure-Requests: 1
-   ReqHeader      Pragma: no-cache
-   ReqHeader      Cache-Control: no-cache
-   ReqHeader      X-Forwarded-For: 192.168.48.1
-   VCL_call       RECV
-   ReqUnset       Host: localhost:8090
-   ReqHeader      host: localhost:8090
-   VCL_return     hash
-   ReqUnset       Accept-Encoding: gzip, deflate
-   ReqHeader      Accept-Encoding: gzip
-   VCL_call       HASH
-   VCL_return     lookup
-   Hit            28 601789.331504 10.000000 0.000000
-   VCL_call       HIT
-   VCL_return     deliver
-   RespProtocol   HTTP/1.1
-   RespStatus     200
-   RespReason     OK
-   RespHeader     content-encoding: gzip
-   RespHeader     content-type: application/x-protobuf
-   RespHeader     date: Fri, 08 Jan 2021 15:09:02 GMT
-   RespHeader     Vary: Accept-Encoding
-   RespHeader     X-Varnish: 32806 28
-   RespHeader     Age: 3010
-   RespHeader     Via: 1.1 varnish (Varnish/6.5)
-   VCL_call       DELIVER
-   VCL_return     deliver
-   Timestamp      Process: 1610121552.734070 0.000197 0.000197
-   Filters        
-   RespHeader     Accept-Ranges: bytes
-   RespHeader     Content-Length: 295
-   RespHeader     Connection: keep-alive
-   Timestamp      Resp: 1610121552.734217 0.000345 0.000147
-   ReqAcct        414 0 414 272 295 567
-   End  

Reproduzindo o problema

Para reproduzir o bug:

  • git clone https://github.com/Baschdl/varnish-ban-setup.git && cd varnish-ban-setup
  • docker-compose up
  • Abra http: // localhost: 8092/5/3 / 1.pbf
  • docker-compose exec varnish varnishadm ban obj.http.url ~ pbf
  • Abra http: // localhost: 8092/5/3 / 1.pbf novamente e você obterá o objeto antigo

Respostas

2 ThijsFeryn Jan 09 2021 at 00:23

O obj.http.url ~ 5/3/4.pbfbanimento que você está emitindo corresponde a um urlcabeçalho de resposta.

Lembre-se: o URL é um cabeçalho de solicitação, não um cabeçalho de resposta. Não há motivo para pânico, o que você está fazendo faz todo o sentido e está relacionado ao escopo do chamado ban lurker .

Banir espreitador

O ban lurker é um thread que processa de forma assíncrona os banimentos na lista de banimentos e associa objetos aos banimentos para remover padrões de objetos do cache.

O ban lurker não opera dentro de um escopo de solicitação, mas apenas está ciente do escopo do objeto.

Para corresponder as informações da solicitação com êxito, o contexto da solicitação pode ser adicionado como um cabeçalho de resposta. E é isso que você está fazendo viaobj.http.url

Então, por que a proibição não funciona?

A razão pela qual seu ban não está funcionando é porque você não configurou obj.http.urlem seu arquivo VCL. Como resultado, o ban lurker não pode combinar nenhum objeto com ele.

Como consertar o problema

A solução é simples: defina os cabeçalhos ausentes no contexto de resposta de back-end, conforme ilustrado abaixo:

sub vcl_backend_response {
    set beresp.http.url = bereq.url;
    set beresp.http.host = bereq.http.host;
}

Quando o back-end responde, e logo antes de o objeto ser armazenado no cache, podemos definir os cabeçalhos ausentes.

Depois disso, o ban lurker será capaz de combinar a expressão de ban com os objetos certos e removê-los do cache.

Não se esqueça de que os objetos não são correspondidos imediatamente: eles só são removidos quando alcançam o ban_lurker_age, que é definido como 1 minuto por padrão.