关于Varnish配置代码功能及缓存逻辑的技术问询
关于Varnish配置代码功能及缓存逻辑的技术问询
Hey there! Let's walk through your Varnish vcl_backend_response code line by line to figure out what it does, whether it's caching your requests, and where it goes wrong.
First, here's your code for reference:
sub vcl_backend_response { if (beresp.status != 200) { return (pass); } set beresp.http.X-Backend = beresp.backend.name; unset beresp.http.cookie; unset beresp.http.Set-Cookie; if (bereq.http.x-render-type == "test" && beresp.http.Content-Type ~ "text/html") { set beresp.http.Cache-Control = "no-store"; } set beresp.http.Cache-Control = "no-store"; if (bereq.http.x-render-type == "test" && beresp.http.Content-Type ~ "text/html") { return (pass); } return (deliver); }
1. 代码逐行解析
- 非200状态码处理:如果后端返回的状态码不是200(比如404、500这类错误),直接返回
pass——这类请求完全不会被缓存,每次都会直接回源获取内容。 - 添加自定义响应头:给响应加上
X-Backend头,值是处理请求的后端服务器名称,方便你排查是哪个后端节点返回的内容,用于调试。 - 清除Cookie相关头:删除响应里的
cookie和Set-Cookie头,这是常见的缓存优化操作——默认情况下,Varnish不会缓存带Cookie的请求/响应,清除这些头能避免缓存被跳过。 - 第一个条件块:如果请求头
x-render-type为"test",且响应是HTML内容,就设置Cache-Control: no-store,告诉Varnish和浏览器不要缓存该响应。但这个设置马上会被后面的代码覆盖,完全无效。 - 全局强制设置Cache-Control:不管前面的条件块有没有触发,这里都会把所有响应的
Cache-Control设为no-store,直接让前面的条件块变成冗余代码。 - 第二个条件块:再次判断
x-render-type=test且是HTML内容的情况,返回pass——直接跳过缓存,把后端响应原样传给客户端。 - 默认交付逻辑:如果前面的条件都没触发,就把响应交给Varnish的交付流程,但因为全局设置了
no-store,最终还是不会缓存。
2. 这段代码会缓存客户端请求吗?
答案是:完全不会缓存任何请求,核心原因有两个:
- 全局的
set beresp.http.Cache-Control = "no-store";强制Varnish不存储任何响应到缓存中,覆盖了所有其他缓存相关设置。 - 就算没有全局设置,
x-render-type=test的HTML请求也会通过return(pass)跳过缓存;非这类请求走到return(deliver)后,也会因为no-store头无法被缓存。
3. 代码存在的问题
- 冗余无效的条件块:第一个设置
no-store的条件块,后续被全局设置完全覆盖,没有任何实际作用,可以直接删除。 - 全局禁用缓存:这是最关键的问题——强制给所有响应加上
no-store头,直接废掉了Varnish的核心缓存功能。 - 逻辑顺序不合理:第二个条件块放在全局缓存头设置之后,虽然不影响功能,但从代码可读性来说,应该先判断是否要跳过缓存,再处理缓存头设置。
修复建议(如果需要启用缓存)
如果希望Varnish正常发挥缓存作用,可以参考下面的修改版本:
sub vcl_backend_response { # 非200响应直接跳过缓存 if (beresp.status != 200) { return (pass); } # 添加调试用的后端标识头 set beresp.http.X-Backend = beresp.backend.name; # 清除Cookie以允许缓存 unset beresp.http.cookie; unset beresp.http.Set-Cookie; # 针对test类型的HTML请求禁用缓存 if (bereq.http.x-render-type == "test" && beresp.http.Content-Type ~ "text/html") { set beresp.http.Cache-Control = "no-store"; return (pass); } # 设置默认缓存时长(可根据业务需求调整) set beresp.ttl = 1h; # 交付响应到缓存和客户端 return (deliver); }
这个版本:
- 移除了冗余的全局
no-store设置 - 提前处理需要跳过缓存的请求逻辑
- 给可缓存的响应设置了默认TTL(缓存有效期)
- 仅针对特定的
testHTML请求禁用缓存
备注:内容来源于stack exchange,提问作者Morteza
相关产品推荐
相关产品推荐

