如何修改Varnish规则:仅指定Query String可缓存,混其他参数则不缓存
解决Varnish中营销Query参数的缓存控制问题
场景与现存问题
- 运行环境:Varnish 搭配 Apache SSL 反向代理,后端是 WordPress
- 初始需求:默认带 Query String 的请求不缓存,但 utm_、gclid 这类广告营销参数不能破坏缓存——要忽略这些参数,复用同页面的缓存
- 现有规则的两个坑:
- 当请求混合了允许的营销参数和未定义参数时(比如
/home?a=1&gclid=x),原规则会重定向到/home?a=1且返回未缓存页面,不符合「保留原URL」的要求 - 改成用
vcl_hash基于处理后的URL哈希时,又会缓存混合参数的请求,有缓存污染风险
- 当请求混合了允许的营销参数和未定义参数时(比如
核心要求
只有当请求只包含指定的营销参数(gclid、cx、ie、cof、siteurl、zanpid、origin、utm_[a-z]+、mr:[A-z]+ 等)时,才允许缓存;只要存在任何未定义的参数,不管有没有混合允许的参数,都不缓存,同时必须保留客户端请求的原URL。
修改后的VCL规则片段
if (req.url ~ "\?") { # 检测是否存在未被允许的Query参数 if (req.url ~ "(?:\?|&)(?!gclid|cx|ie|cof|siteurl|zanpid|origin|utm_[a-z]+|mr:[A-z]+)\w+=") { set req.http.X-Cacheable = "NO:Contains non-allowed query parameters"; return (pass); } # 仅含允许参数时,移除这些参数以复用缓存(不影响客户端看到的URL) else { set req.url = regsuball(req.url, "(?:\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|utm_[a-z]+|mr:[A-z]+)=[^&]*", ""); # 清理替换后可能残留的?或& set req.url = regsub(req.url, "\?$", ""); set req.url = regsub(req.url, "&$", ""); } }
规则逻辑说明
- 先判断请求是否带 Query String,不带的话正常走缓存流程
- 关键正则
(?:\?|&)(?!gclid|cx|ie|cof|siteurl|zanpid|origin|utm_[a-z]+|mr:[A-z]+)\w+=:- 用负向前瞻
(?!...)排除所有白名单内的参数,只要匹配到不在白名单里的参数,就标记为不可缓存并直接 pass,而且不会修改客户端的请求URL - 如果所有参数都在白名单里,就用正则替换把这些营销参数全部移除,修改 Varnish 内部的
req.url用于哈希计算——这样不同的营销参数请求会命中同一个缓存,同时客户端看到的还是原来的带参数URL
- 用负向前瞻
内容的提问来源于stack exchange,提问作者sash
相关产品推荐
相关产品推荐

