![我可以将 Varnish Cache 与我的 Cookie 一起使用吗](https://linux22.com/image/612679/%E6%88%91%E5%8F%AF%E4%BB%A5%E5%B0%86%20Varnish%20Cache%20%E4%B8%8E%E6%88%91%E7%9A%84%20Cookie%20%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8%E5%90%97.png)
我很乐意利用 varnish 的强大功能来缓存我的 php 密集型应用程序,该应用程序每天为大约 40 万人提供服务。
该应用程序通过启动多个线程来提取搜索数据,这些线程会卷曲 XML,因此您可以想象会产生大量新线程,并且这些线程会保持打开状态几秒钟,从而使页面加载只需几秒钟。
每个搜索结果页面的缓存将大大加快用户体验。
这就是我的问题的基础。
我们的搜索结果页面需要转换代码跟踪。因此,用户从源/引荐来源 A 来到我们的页面 domain.com/search/?q=something&source=A,系统会选择适当的转换跟踪代码(与引荐来源 A 相关)并将其输出到页面。Cookie 也会被丢弃,因此下次用户返回页面时会检查 cookie 是否存在,如果是,则选择在 HTML 中显示正确的转换代码。
这样,转化跟踪可以在会话内外进行。
问题是,考虑到我们对 cookie 的要求,是否可以在这种情况下使用 varnish 进行缓存?我们可以以某种方式配置 VCL 来处理这些 cookie 吗?如果可以,我们应该写些什么?
谢谢
答案1
我发现,思考 Varnish 的有效性和实现的最简单方法是通过组合来思考。每个变量都会产生成倍增加的组合。简而言之,这些变量是:主机、URI 和标头/cookie。
例如,这些是 Varnish 缓存中的不同对象
domain.com/search/?q=something
domain.com/search/?q=something&source=A
domain.com/search/?q=something&source=B
domain.com/search/?q=something&source=A + nocookie
domain.com/search/?q=something&source=A + cookie1
domain.com/search/?q=something&source=A + cookie2
domain.com/search/?q=something&source=B + nocookie
domain.com/search/?q=something&source=B + cookie1
domain.com/search/?q=something&source=B + cookie2
然而: 只要来源没有太大差异,并且服务器不负责根据源输出不同的内容,使用 Varnish 应该是半简单的......但前提是你先做一些操作。
由于您可以使用 Varnish 来操纵客户端的大部分请求,因此您可以在将请求的 URI 发送到后端服务器之前实际删除 &source=A 或 &source=B。这实际上会将所有这些请求变成:
domain.com/search/?q=something&source=A + nocookie
domain.com/search/?q=something&source=A + cookie1
domain.com/search/?q=something&source=A + cookie2
domain.com/search/?q=something&source=B + nocookie
domain.com/search/?q=something&source=B + cookie1
domain.com/search/?q=something&source=B + cookie2
变成这样:
domain.com/search/?q=something
之前是 6 次未命中且 0 次命中,现在变成了 1 次未命中且 5 次命中
因此客户端向 Varnish 提出如下请求:
domain.com/search/?q=something&source=A + cookie1
Varnish 实际上在第一个请求中从后端(例如 Apache)请求此信息:
domain.com/search/?q=something
然后缓存以供后续请求(从而大大提高命中率)。这称为“规范化”。
然后,静态 JavaScript 文件当然会通过引用 URI 查询字符串来完成其工作,并根据源查询字符串执行一些 DOM 操作(类似于 Google Analytics 所做的)。
因此对于客户端来说,&source=A 将被维护,并且 JavaScript 可以相应地使用它;只要 JavaScript 负责动态更改内容,在 Varnish 将请求发送到后端之前,您应该可以毫无问题地从请求中删除所有或大部分 cookie 或查询字符串。
您还可以缓存您的 XML 请求,只要它们是 GET 请求。
基本上,Varnish 的核心就是“规范化”后端请求,这样 URI/cookie/headers 就不会影响服务器返回的内容,在发送到后端之前应该进行处理,也就是规范化。
在 Varnish 中重新格式化 URI: https://stackoverflow.com/questions/3547384/can-i-reformat-my-url-parameters-with-varnish
如果您需要根据 cookie 动态缓存内容,则可以使用 vcl_hash 来实现:https://www.varnish-cache.org/trac/wiki/VCLExampleCacheCookies 这当然会降低你的命中率,所以最好将这样的功能交给 JavaScript 来处理,并告诉 Varnish 不要缓存特定的端点:例如
// don't cache this endpoint, this content changes based on the referrer
if (req.url ~ '/ajax/get_referrer/') { return (pass); }
你的问题中我唯一不明白的部分是:
Cookie 也被删除,因此下次用户返回页面时会检查 cookie 是否存在,如果是,则选择在 HTML 中显示正确的转换代码。
只要后端服务器不需要查看 cookie 或设置 cookie,也就是说,只要 JavaScript 负责处理 DOM 工作,您就应该清楚。请注意,如果每个用户的“来源/引用者”不同,您还应该告诉 Varnish 不要缓存用于获取所需数据的任何端点。
您还应该注意,您只能在 Varnish 中缓存 GET 和 HEAD 请求。如果您的搜索或 JavaScript 使用 POST 或任何其他请求类型,则不应缓存它们。
我绝对建议在开发服务器上完成所有操作。您还需要考虑许多其他因素,例如提供 PDF/视频/音频(又称管道请求)、忽略页面,以及许多其他特定于您情况的考虑因素。