postgis - 添加了 Varnish 禁令,但返回了旧对象

标签 postgis varnish mapbox-gl-js varnish-vcl http-caching

我在切片服务器前使用 Varnish 来缓存 Mapbox 切片。为了删除旧的图 block ,我打算使用禁令来有效地删除大量缓存的图 block 。我的问题是 varnish 仍然使用缓存的对象(至少响应中的 age 表明了这一点)并且不联系后端。

我首先请求 http://varnish/5/3/4.pbf,然后使用 curl -X BAN -H 'X-Purge-Regex: 5/3/4.pbf 添加禁令' varnishvarnishadm 然后禁止 obj.http.url ~ 5/3/4.pbf 然后请求 http://varnish/5/再次3/4.pbf。

一开始我的禁令列表是空的:

Present bans:
1610117471.434488     1 C

使用 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>

并出现在禁止列表中

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

再次请求http://varnish/5/3/4.pbf后,ban列表显示使用了ban

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

但是响应的年龄不为0,因为它仍然是第一个请求的对象。

不久之后,禁令被解除:

Present bans:
1610117471.434488     1 C  

我的 vcl_recv 看起来像这样,但错误可能在其他地方,因为它也不适用于 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);
                }
        }
}

我还尝试使用 https://stackoverflow.com/a/61507014 中的 vcl_purge但这似乎对禁令没有帮助(?)。

我使用 X-Purge-Regex header 来不必担心必须转义 https://stackoverflow.com/a/38526921 中的特殊字符但仅仅像 obj.http.url ~ 0 这样的禁令是行不通的。

我使用的是 varnish 6.5 和 vcl 4.0。

禁止请求

*   << 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            

添加禁令后获取

*   << 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  

重现问题

重现该错误:

  • git 克隆 https://github.com/Baschdl/varnish-ban-setup.git && cd varnish-ban-setup
  • docker-compose up
  • 打开http://localhost:8092/5/3/1.pbf
  • docker-compose exec varnish varnishadm ban obj.http.url ~ pbf
  • 再次打开http://localhost:8092/5/3/1.pbf,您将获得旧对象

最佳答案

您发出的 obj.http.url ~ 5/3/4.pbf 禁令与 url 响应 header 匹配。

Remember: the URL is a request header, not a response header. No reason to panic, what you're doing makes perfect sense, and is related to the scope of the so-called ban lurker.

禁止潜伏者

禁令潜伏者是一个线程,它异步处理禁令列表上的禁令,并将对象与禁令进行匹配,以便从缓存中删除对象模式。

禁令潜伏者不在请求范围内操作,而只知道对象范围。

为了成功匹配请求信息,可以添加请求上下文作为响应头。这就是您通过 obj.http.url

所做的事情

那么为什么禁令不起作用呢?

您的禁令不起作用的原因是您没有在 VCL 文件中设置 obj.http.url 。因此,禁令潜伏者无法匹配任何对象。

如何解决问题

解决方案很简单:在后端响应上下文中设置缺少的 header ,如下所示:

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

当后端响应时,在对象存储到缓存中之前,我们可以设置丢失的 header 。

之后,禁令潜伏者将能够将禁令表达式与正确的对象相匹配,并将它们从缓存中删除。

Don't forget the objects aren't immediately matched: they are only removed when they reach the ban_lurker_age, which is set to 1 minute by default.

关于postgis - 添加了 Varnish 禁令,但返回了旧对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65632023/

相关文章:

PostgreSQL:无法对某些数据类型使用 DISTINCT

python - 加速从 netcdf 插入点数据

php - Varnish 缓存 - 页面缓存多长时间?

caching - Varnish 和 Google Analytics

reactjs - 我可以自动聚焦 mapbox-gl react 地理编码器吗

linux - 什么是 POSTGIS_VERSION 2.1.7+dfsg-3~94.git954a8d0.pgdg80+1?

java - 通过 ProcessBuilder Java 找不到 shp2pgsql、psql 命令

Varnish :如果响应为404,则重写URL

node.js - MapboxGL 客户端的自托管矢量切片呈现不正确

javascript - Mapbox GL设置符号图层的不透明度