当Varish宿主忽略查询字符串参数时,动态页面无法正确显示

时间:2020-08-20 作者:Daveh0

我有一个使用Varnish的托管WP站点。我有一个登录页,它根据通过查询字符串传递的几个参数显示适当的图像。例如,根据用户请求此页面的位置,URL可能是www.example.com/landing?v=1www.example.com/landing?v=2... 每个页面都会包含不同的徽标图像,这取决于v 在查询字符串中。

Varnish的默认行为似乎是为页面的缓存版本提供服务,并忽略(或删除)任何查询字符串参数。因此,上面的两个URL显示相同的确切页面(使用编码到页面中的默认图像),这两个URL都不正确。

<?php
$logoBase = \'path/to/logo-\';
$logoSrc = isset($_GET[\'v\']) ? $logoBase . $_GET[\'v\'] : \'default\';
$logoSrc .= \'.svg\';
?>

<img src="<?php echo $logoSrc ?>" alt="logo"> 

With that, a couple questions:

理想情况下,我希望使用该页面的缓存版本,并仍然动态显示徽标,但有些事情告诉我这是不可能的。是吗?如果是这样,is there some configuration file that will tell Varnish to do just that rather than rendering it 100% from the cached version as if there was no query string?

如果不可能,is there a way to specify that a page is not to be served from the cache and to render it dynamically, fresh from scratch on each request while still serving all other pages from the cache?

And what about Google Analytics UTM parameters? 即使它不影响页面的显示方式,忽略这些参数也是很有问题的。How is that typically handled?

除非有一个非常简单的配置答案,否则我不会要求任何代码。我只需要一个起点(关于WP最佳实践的建议,因为它涉及太多的缓存和动态内容),这样我就可以弄清楚我可以配置自己什么(以及应该以不同的方式配置什么),以及我需要让托管管理员修改什么。

1 个回复
SO网友:Thijs Feryn

使用查询字符串参数缓存内容Varnish对URL进行哈希运算,并将此值用作其缓存键。当URL中的单个值更改时,缓存键也会更改。这将导致缓存未命中。

查询字符串参数极易发生这种情况:省略参数、添加参数或更改参数顺序可能会导致缓存未命中。

添加以下VCL片段将确保查询字符串参数按字母顺序排序,这将提高命中率:

import std;

sub vcl_recv {
    set req.url = std.querysort(req.url);
}
动态徽标VCL 编程语言使您能够灵活地决定如何在边缘做出某些决策。尽管缓存了值,或者源服务器返回了某个值,但您仍然可以通过编写一些VCL代码来更改客户端看到的内容。

实际上,您可以捕获对徽标的请求,并且仍然可以在内部将请求重新路由到不同的URL。您甚至可以内省查询字符串参数来组成动态徽标的URL。

实现这一点所需的VCL代码取决于许多因素。由您来描述这些规则和所需的逻辑。

清理JS库用于跟踪的UTM参数查询字符串参数可以在VCL中剥离。源服务器不需要它们来呈现页面,添加这些参数只会导致更多的缓存未命中。

以下是一些VCL来清理您的URL:

sub vcl_recv {
  # Remove tracking parameters
  if (req.url ~ "(\\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
    set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\\-\\.%25]+)", "");
    set req.url = regsuball(req.url, "\\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\\-\\.%25]+)", "?");
    set req.url = regsub(req.url, "\\?&", "?");
    set req.url = regsub(req.url, "\\?$", "");
  }

  # Strip HTML anchors
  if (req.url ~ "\\#") {
    set req.url = regsub(req.url, "\\#.*$", "");
  }

  # Strip a trailing ? if it exists
  if (req.url ~ "\\?$") {
    set req.url = regsub(req.url, "\\?$", "");
  }
}
首先,使用regsuball() 查找并替换调用下一步是从URL中删除HTML锚定,最后我们删除后面的问号,因为它们意味着没有使用查询字符串参数摘要VCL有必要的语法来解决您的问题。您可能会使用regsub()regsuball() 用于从URL中删除众所周知的垃圾,以确保更好的命中率。

您也可以使用VCL执行动态决策,但在我们讨论VCL实现之前,您必须描述必要的逻辑和规则。