首页 > 解决方案 > Magento 2 为不同的客户显示不同的价格导致 Fastly 出现问题

问题描述

我只想为不同的客户显示不同的价格。但我不想让任何可缓存的块为假。问题是当客户加载类别页面然后它缓存生成并且缓存页面显示的所有客户。我为普通的magento FPC修复了这个问题。但是对于 Fastly 它不起作用,有什么想法吗?

标签: magento2fastly

解决方案


据我了解,您有一个页面(“类别”),其中每个客户的内容都不同,但您发现请求您的“类别”页面的第一个客户导致他们的内容变体被缓存和因此所有其他客户都看到了从缓存中提供的完全相同的响应。

例如,您有两个客户:A 和 B。A 客户应该看到内容“A”,而 B 客户应该看到内容“B”。目前,您会发现,当客户 A 先请求页面,然后客户 B 请求同一页面时,客户 B 现在看到的是内容“A”(因为该版本的响应首先被缓存)。

这通常是您使用Vary可能带有会话 ID 或 cookie 标头的响应标头的地方。

Fastly 有一篇博客文章解释了Vary标题的作用,以及许多您可能希望如何使用它的示例:
https ://www.fastly.com/blog/getting-most-out-vary-fastly

Fastly 还有一个Vary可能有帮助的参考页面:
https ://developer.fastly.com/reference/http-headers/Vary/

您实际上可以Vary在 Fastly 的“食谱”页面上找到使用 cookie 的示例(尽管它不太符合您的确切要求):
https ://developer.fastly.com/solutions/recipes/vary-based-on-一块饼干

这个例子不太正确的原因是因为他们使用一个称为logged-in请求头的自定义头来改变内容响应。您需要一个始终由客户端发送并包含唯一值(例如 cookie)的请求标头。

所以我将演示它的修改版本:
https ://fiddle.fastlydemo.net/fiddle/e3aa91a5

注意:我建议您联系您的 Fastly 支持联系人,因为他们可能会提供比我在下面建议的解决方案更好的解决方案。我担心的是,我相信 Fastly 缓存中单个对象的唯一变体的数量可能存在限制,例如,如果限制是 100 个变体(我编了这个数字,我不知道它会是什么),你有 101 个客户,那么这个解决方案对你不起作用。

对于后代(如果将来删除 Fastly 食谱页面或我自己的示例),我将复制粘贴下面的相关代码......

注意:如果您在理解 VCL 和我在下面提到的各种子例程方面需要帮助,那么您可以在这里阅读:https ://developer.fastly.com/learning/vcl/using每个子例程的更具体的参考指南这里:https ://developer.fastly.com/reference/vcl/subroutines/

vcl_recv

在下面的代码片段中,在vcl_recv子例程中,我记录了传入客户端请求设置的 Cookie。我这样做只是为了让您可以直观地看到哪个客户提出了请求。

vcl_recv子例程是 Fastly 服务器执行的第一个子例程,这意味着您可以检查和操作来自客户端的传入请求,然后再在缓存中查找或向后端服务器发出请求(以获取请求的内容,如果它还不存在于缓存中)。

log "user-login: " + req.http.cookie:user-login;

vcl_fetch

在下面的代码片段中,在vcl_fetch子例程中,我首先检查请求 URL 匹配/anything,如果匹配,然后查看发出请求的客户端是否user-login设置了 cookie。如果他们这样做了,那么我会操纵来自后端服务器的响应以包含一个Vary标头Cookie作为其值(或者如果后端响应中已经有一个VaryHTTP 标头,我会附加 Cookie)。

子程序在vcl_fetch你的后端服务器发送内容并且fastly的缓存节点接收到它之后执行,但是缓存服务器还没有缓存响应(一旦vcl_fetch子程序执行完成它会缓存响应),这意味着它是一个完美的是时候操作响应并添加VaryHTTP 标头了。

if (req.url ~ "^/anything") {
  if (req.http.cookie:user-login) {
    if (beresp.http.vary) {
      set beresp.http.vary = beresp.http.vary ",Cookie";
    } else {
      set beresp.http.vary = "Cookie";
    }
  }
}

这段代码演示的是:当客户 A 和 B 都登录到您的站点并且他们都设置了相关的会话 cookie 时,当他们中的任何一个请求您的类别页面时,他们都会(最初)去您的后端服务器获取内容(因为什么都不会被缓存),然后每个唯一的响应将使用来自传入请求的值进行缓存。

您可以在此处使用 Fastly 的“小提琴”工具(用于测试和调试)看到一个完整的工作示例: https ://fiddle.fastlydemo.net/fiddle/e3aa91a5

我希望这在某种程度上有所帮助。否则,我建议联系 Fastly 支持。https://support.fastly.com/hc/en-us有一个在线社区可以帮助您(屏幕右下方还有一个“语音气泡”图标,您可以在其中深入联系支持团队,并通过在线表格向他们发送电子邮件)。

更新

我对上述建议有一些反馈,并且(正如我预测的那样)Vary: Cookie不建议使用...

如果您这样做的原因是因为每个用户的来源响应不同,那么实际上Cache-Control: private更好。这样 Fastly 就不会尝试缓存它,但浏览器仍然会缓存它。

但是,如果响应的粒度实际上要小得多,例如,您只是因为有些人可以访问内容而其他人不能访问,那么缓存内容并在边缘(很像:https ://developer.fastly.com/solutions/recipes/vary-based-on-a-cookie )


推荐阅读