【发布时间】:2021-10-29 04:48:46
【问题描述】:
我一直在尝试根据清漆的响应大小进行缓存。
其他答案建议使用Content-Length 来决定是否缓存,但我使用的是InfluxDB(清漆反向代理),它以Transfer-Encoding:Chunked 响应,它省略了Content-Length 标头,我无法弄清楚响应的大小。
有什么方法可以访问响应正文大小并在vcl_backend_response 中做出决定?
【问题讨论】:
我一直在尝试根据清漆的响应大小进行缓存。
其他答案建议使用Content-Length 来决定是否缓存,但我使用的是InfluxDB(清漆反向代理),它以Transfer-Encoding:Chunked 响应,它省略了Content-Length 标头,我无法弄清楚响应的大小。
有什么方法可以访问响应正文大小并在vcl_backend_response 中做出决定?
【问题讨论】:
当 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-url 和 x-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 容器中运行这一事实?