如何根据 Varnish 中的大小进行缓存?
How to cache based on size in Varnish?
我一直在尝试根据清漆的响应大小进行缓存。
其他答案建议使用 Content-Length
来决定是否缓存,但我使用的是 InfluxDB(Varnish 反向代理)并且它以 Transfer-Encoding:Chunked
响应,它省略了 Content-Length
header 而且我无法计算出响应的大小。
有什么方法可以访问响应 body 大小并在 vcl_backend_response
中做出决定?
缓存未命中:分块传输编码
当 Varnish 处理来自源的传入块时,它无法提前知道将接收到多少数据。 Varnish 将数据流式传输到客户端并按字节存储数据字节。
一旦收到 0\r\n\r\n
标记流的结束,Varnish 将最终确定 object 存储并计算总字节数。
缓存命中:内容长度
下次请求 object 时,Varnish 不再需要使用 Chunked Transfer Encoding,因为它在缓存中有完整的 object 并且知道大小。那时 Content-Length
header 是响应的一部分,但是这个 header 在 VCL 中无法访问,因为它似乎是在执行 sub vcl_deliver {}
之后生成的。
事后删除 object 秒
通过 VSL 监控它们的大小,可以事后删除 objects。
以下命令将查看 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"
Replace domain.com
with the actual hostname of your service and set /
to the URL of the actual endpoint you're trying to remove from the cache.
不要忘记将以下代码添加到您的 VCL 文件中,以确保 x-url
和 x-host
header 可用:
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;
}
结论
虽然没有 turn-key 解决方案来访问 VCL 中 body 的大小,但我建议的 hacky 解决方案是我们在事后删除 objects 的唯一方法我能想到。
我一直在尝试根据清漆的响应大小进行缓存。
其他答案建议使用 Content-Length
来决定是否缓存,但我使用的是 InfluxDB(Varnish 反向代理)并且它以 Transfer-Encoding:Chunked
响应,它省略了 Content-Length
header 而且我无法计算出响应的大小。
有什么方法可以访问响应 body 大小并在 vcl_backend_response
中做出决定?
缓存未命中:分块传输编码
当 Varnish 处理来自源的传入块时,它无法提前知道将接收到多少数据。 Varnish 将数据流式传输到客户端并按字节存储数据字节。
一旦收到 0\r\n\r\n
标记流的结束,Varnish 将最终确定 object 存储并计算总字节数。
缓存命中:内容长度
下次请求 object 时,Varnish 不再需要使用 Chunked Transfer Encoding,因为它在缓存中有完整的 object 并且知道大小。那时 Content-Length
header 是响应的一部分,但是这个 header 在 VCL 中无法访问,因为它似乎是在执行 sub vcl_deliver {}
之后生成的。
事后删除 object 秒
通过 VSL 监控它们的大小,可以事后删除 objects。
以下命令将查看 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"
Replace
domain.com
with the actual hostname of your service and set/
to the URL of the actual endpoint you're trying to remove from the cache.
不要忘记将以下代码添加到您的 VCL 文件中,以确保 x-url
和 x-host
header 可用:
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;
}
结论
虽然没有 turn-key 解决方案来访问 VCL 中 body 的大小,但我建议的 hacky 解决方案是我们在事后删除 objects 的唯一方法我能想到。