我可以将 Varnish Cache 与我的 cookie 一起使用吗

B p*_*B p 1 varnish

我很想利用 varnish 的强大功能来缓存我的 php 密集型应用程序,该应用程序每天为大约 40 万人提供服务。

该应用程序通过触发多个卷曲 XML 的线程来获取搜索数据,因此您可以想象新线程会产生很多,并且这些线程会保持打开状态几秒钟,从而使页面加载几秒钟。

每个搜索结果页面的缓存将大大加快用户体验。

所以这是我问题的基础。

我们的搜索结果页面需要转换代码跟踪。所以用户来自source/referer A,到我们的页面domain.com/search/?q=something&source=A,选择合适的转换跟踪代码(与referer A相关)输出到页面。Cookie 也会被删除,因此用户下次返回页面时会检查 cookie 是否存在,如果存在,则选择在 HTML 中显示正确的转换代码。

通过这种方式,转换跟踪在会话中和会话外工作。

问题是,鉴于我们对 cookie 要求的了解,是否可以在这种情况下使用 varnish 进行缓存?我们能否以某种方式配置 VCL 来处理这些 cookie,如果可以,我们应该写什么?

谢谢

小智 5

我发现考虑 Varnish 的有效性和实现的最简单方法是组合思考。每个变量都会以指数方式创建更多的组合。简而言之,这些变量是:host、URI 和 headers/cookies。

例如,这些是 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
Run Code Online (Sandbox Code Playgroud)

但是: 只要来源变化不大,并且服务器不负责根据来源输出不同的内容,那么使用 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
Run Code Online (Sandbox Code Playgroud)

就这样:

domain.com/search/?q=something
Run Code Online (Sandbox Code Playgroud)

什么是 6 次未命中且未命中,现在是 1 次未命中和 5 次命中

所以客户从 Varnish 请求这个:

domain.com/search/?q=something&source=A + cookie1
Run Code Online (Sandbox Code Playgroud)

并且 Varnish 实际上从后端(例如 Apache)请求第一个请求:

domain.com/search/?q=something
Run Code Online (Sandbox Code Playgroud)

然后为后续请求缓存(从而显着提高您的命中率)。这称为“规范化”。

然后当然静态 JavaScript 文件将通过引用 URI 查询字符串来完成它的工作,并根据源查询字符串进行一些 DOM 操作(类似于 Google Analytics 所做的)。

所以对于客户端,&source=A 将被维护,JavaScript 可以相应地使用它;并且只要 JavaScript 负责动态更改内容,在 Varnish 将请求发送到后端之前,您应该可以从请求中删除所有或大部分 cookie 或查询字符串。


您还可以缓存您的 XML 请求,只要它们是 GET 请求。

基本上,使用 Varnish 的游戏名称都是关于“规范化”后端请求,以便不影响从服务器返回的内容的 URI/cookies/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); }
Run Code Online (Sandbox Code Playgroud)

我在你的问题中唯一不明白的部分是:

Cookie 也会被删除,因此用户下次返回页面时会检查 cookie 是否存在,如果存在,则选择在 HTML 中显示正确的转换代码。

只要后端服务器不需要看到cookie或设置cookie,即只要JavaScript负责处理DOM工作,您就应该清楚。请注意,如果每个用户的 'source/referrer' 不同,您还应该告诉 Varnish 不要缓存用于获取所需数据的任何端点。

您还应该注意,您应该只在 Varnish 中缓存 GET 和 HEAD 请求。如果您的搜索或 JavaScript 使用 POST 或任何其他请求类型,则不应缓存它们。


我绝对建议在开发服务器上做所有事情。您将有许多其他因素需要考虑,例如交付 PDF/视频/音频(又名管道请求)、忽略页面以及更多针对您的情况的独特考虑。