【问题标题】:How to cache based on size in Varnish?如何在 Varnish 中根据大小进行缓存?
【发布时间】:2021-10-29 04:48:46
【问题描述】:

我一直在尝试根据清漆的响应大小进行缓存。
其他答案建议使用Content-Length 来决定是否缓存,但我使用的是InfluxDB(清漆反向代理),它以Transfer-Encoding:Chunked 响应,它省略了Content-Length 标头,我无法弄清楚响应的大小。
有什么方法可以访问响应正文大小并在vcl_backend_response 中做出决定?

【问题讨论】:

    标签: influxdb varnish


    【解决方案1】:

    缓存未命中:分块传输编码

    当 Varnish 处理从源端传入的块时,它事先不知道会收到多少数据。 Varnish 将数据流式传输到客户端并按字节存储数据。

    一旦收到0\r\n\r\n 来标记流的结束,Varnish 将完成对象存储并计算总字节数。

    缓存命中:内容长度

    下次请求对象时,Varnish 不再需要使用 Chunked Transfer Encoding,因为它在缓存中拥有完整的对象并且知道大小。此时,Content-Length 标头是响应的一部分,但在 VCL 中无法访问此标头,因为它似乎是在执行 sub vcl_deliver {} 之后生成的。

    事后删除对象

    通过 VSL 监控对象的大小,可以在事后移除对象。

    以下命令将查看 VSL 输出的后端请求记帐字段并检查总大小。如果大小大于 5MB,则生成输出

    varnishlog -g request -i berequrl -q "BereqAcct[5] > 5242880"
    

    以下是一些潜在的输出:

    *   << Request  >> 98330
    **  << BeReq    >> 98331
    --  BereqURL       /
    

    此时,您知道/ 资源大于 5 MB。然后,您可以尝试使用以下命令将其从缓存中删除:

    varnishadm ban "obj.http.x-url == / && obj.http.x-host == domain.com"
    

    domain.com 替换为您的服务的实际主机名,并将 / 设置为您尝试从缓存中删除的实际端点的 URL。

    不要忘记将以下代码添加到您的 VCL 文件中,以确保 x-urlx-host 标头可用:

    sub vcl_backend_response {
        set beresp.http.x-url = bereq.url;
        set beresp.http.x-host = bereq.http.host;
    }
    
    sub vcl_deliver {
        unset resp.http.x-url;
        unset resp.http.x-host;
    }
    

    结论

    虽然在 VCL 中没有访问 body 大小的统包解决方案,但我建议的 hacky 解决方案是在事后删除对象是我唯一能想到的。

    【讨论】:

    • 谢谢你的详细解释,你的回答让我意识到为什么编码被分块,我可以采取另一种方法,如果我设置beresp.do_stream= false,这反过来会产生 Varnish 响应仅在完全处理后才使用数据(因此使 Content-Length 可用),您会建议反对它吗(它会在第一次数据检索时导致足够大的延迟)吗?考虑到这两个服务都在同一个 docker 容器中运行这一事实?
    • 在 Varnish 中显式缓冲后端响应导致的潜在延迟很难预测。这完全取决于您的后端发送响应所需的时间。 Varnish 不会成为瓶颈,因为 Varnish 可以轻松解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2016-06-22
    • 2011-07-24
    • 1970-01-01
    • 2012-09-02
    • 2021-08-27
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多