如何使用Varnish缓存忽略特定查询参数?指定请求场景实例
如何让Varnish忽略动态查询参数生成缓存键?
我完全懂你的困扰——那个自动生成的_参数每次请求都不一样,直接导致Varnish每次都生成新的缓存键,根本没法复用之前的缓存,这完全违背了缓存的初衷。别担心,我们可以通过调整Varnish的VCL配置来解决这个问题。
先给你说清楚为什么之前的req.url ~ "^/swatches/(.*)$"配置没用:这个规则只是告诉Varnish“要缓存这个路径下的请求”,但它并没有改变Varnish生成缓存键的逻辑。Varnish默认是用**完整的请求URL(包括所有查询参数)**来生成缓存UID的,所以只要_参数的值变了,缓存键就跟着变,自然命中不了旧缓存。
下面给你两种实用的解决方案,你可以根据自己的需求选:
方案一:修改请求URL,移除动态参数
这种方法会直接修改req.url,把那个烦人的_参数去掉,这样Varnish生成缓存键的时候就只会用到你需要的参数了,同时后端收到的请求也会去掉这个参数。
在你的VCL文件的vcl_recv阶段添加这段代码:
sub vcl_recv { # 匹配/swatches/ajax/media/开头的请求URL if (req.url ~ "^/swatches/ajax/media/\?") { # 移除所有格式为&_=xxx或_=xxx的参数 set req.url = regsuball(req.url, "&?_=[^&]*", ""); # 处理替换后可能出现的?&格式问题(比如_是第一个参数的情况) set req.url = regsub(req.url, "\?&", "?"); # 如果最后只剩一个?,直接去掉它 set req.url = regsub(req.url, "\?$", ""); } }
如果你的/swatches/路径下所有请求都需要忽略这个_参数,只要把匹配规则改成req.url ~ "^/swatches/"就行。
方案二:自定义缓存键,排除动态参数
如果你不想修改后端收到的请求URL,只是想让Varnish生成缓存键的时候忽略_参数,可以在vcl_hash阶段自定义缓存键的生成逻辑:
sub vcl_hash { # 用处理后的URL(移除_参数)代替默认的req.url hash_data(regsuball(req.url, "&?_=[^&]*", "")); # 保留主机头作为缓存键的一部分(多域名场景下必须加) hash_data(req.http.host); # 如果你的场景需要其他缓存维度(比如特定Cookie),可以在这里添加hash_data() }
这个方法的好处是,后端依然会收到完整的请求URL(包括_参数),但Varnish的缓存键只基于去掉_参数后的URL生成,完美兼顾了缓存和后端需求。
两种方法都能解决你的问题,选哪个看你具体的业务场景就好。
内容的提问来源于stack exchange,提问作者Tanel Tammik
相关产品推荐
相关产品推荐

