从缓存发出清漆服务请求(清除 cookie)
Make varnish serve request from cache (cookies are cleaned)
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-54516992-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-54516992-1');
</script>
</head>
<body>
test
</body>
</html>
后端。这是 Python + Django。请不要害怕我只是在这里设置了一个 cookie (render_to_response),然后我需要一个在断点处停止的地方(在下面的代码中它通过注释显示在它所在的位置)。
class HomeView(TemplateView):
template_name = "home/home.html"
def render_to_response(self, context, **response_kwargs):
response = super(TemplateView, self).render_to_response(context, **response_kwargs)
response.set_cookie('sort_on', 'title')
return response
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context # Breakpoint.
varnishd 出于学习目的,我只是清理所有 cookie。
$ varnishd -V
varnishd (varnish-6.0.6 revision 29a1a8243dbef3d973aec28dc90403188c1dc8e7)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2019 Varnish Software AS
VCL
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
call remove_proprietary_cookies;
if (req.http.Cookie) {
return (pass);
}
}
sub remove_proprietary_cookies{
set req.http.Cookie = regsuball(req.http.Cookie, ".*", "");
}
然后我重新加载页面几次以使 cookie 确实存在。
在Chrome中:
document.cookie
"sort_on=title; _ga=GA1.1.988164671.1586849704; _gid=GA1.1.995393496.1586849704; _gat_gtag_UA_54516992_1=1"
饼干图片(以上文字的重复):
好的。我们检查过 Cookie 已设置。现在让我们检查cookie是否正确清理。
我在 braakpoint 停下来检查 cookie。值为 {}。
嗯。所有的饼干似乎都被清理了。
问题:
重新加载时,我不断地来到断点。这意味着 Varnish 将请求传递给后端。换句话说 if (req.http.Cookie) 没有像我预期的那样工作。我希望在上一步中我已经删除了 cookie。然后我检查 cookie 是否存在。而且不应该有任何。
你能帮帮我吗:
明白这是怎么回事了。
组织一切,这样如果我错误地删除了 cookie,我绝对应该删除它们。
使 Varnish 从缓存中处理此请求,而不将其传递到后端。
==============4 月 16 日添加=================
++++++++++++++++++++++++++++++++++++++++++++++++++++ +++
我已经将 Varnish 升级到 6.4:
michael@michael:~$ varnishd -V
varnishd (varnish-6.4.0 revision 13f137934ec1cf14af66baf7896311115ee35598)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2020 Varnish Software AS
我们要测试的内容:
- 在后端设置 Google 分析 cookie 和 cookie。
- 让 Varnish 删除所有 cookie 并缓存响应。
- 检查请求是否只传递到后端一次。
然后我在varnish后面组织了nginx(只是为了记录请求)。 Nginx 在 8090 监听。这是日志配置:
log_format main '[$time_local] $http_cookie';
Cookies:
- 在 HTML 中,我组织了 Google Analytics 的跟踪。
- 在后端,我将名为 "sort_on" 的 cookie 设置为值为 "title"。
+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++
如果我们不切饼干,日志看起来是这样的(这只是为了比较):
127.0.0.1 - - [16/Apr/2020:08:11:05 +0300] "GET / HTTP/1.1" sort_on=title; _ga=GA1.1.236170900.1587013419; _gid=GA1.1.2033785209.1587013419 200 334 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "127.0.0.1"
+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++
varnish.ctl
vcl 4.1;
import cookie;
backend default {
.host = "127.0.0.1";
.port = "8090";
}
sub vcl_recv {
unset req.http.Cookie;
if (req.http.Cookie) {
return (pass);
}
}
Nginx 将请求传递给后端。后端位于端口 8080。
总之听什么听哪里:
Varnish - 8000
Nginx - 8090
Backend - 8080
启动varnishd:
michael@michael:~$ sudo varnishd -f /home/michael/PycharmProjects/varnish/varnish.vcl -a localhost:8000
打开Chrome,多次加载页面:
Nginx的访问日志:
127.0.0.1 - - [16/Apr/2020:08:12:49 +0300] "GET / HTTP/1.1" - 200 334 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "127.0.0.1"
127.0.0.1 - - [16/Apr/2020:08:13:21 +0300] "GET / HTTP/1.1" - 200 334 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "127.0.0.1"
我们可以看到没有cookie。没关系。饼干被切断了。
问题: 请求不可避免地传递到后端。我总是在断点处停下来。
你能给我一些如何处理这个问题的建议吗?
Varnish 不会查看 Cookie
请求 header 的内容,而是检查 header 是否存在。
你需要做的是检查 Cookie
header 是否为空,如果是,则将其全部删除。
只需在您的 regsub
语句后添加:
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
使流程更灵活一些
实际上,您可能不会删除所有 cookie,而只会删除对您的应用程序来说不是必需的 cookie。
您可以使用此语句删除所有 cookie,但您的应用程序需要的 cookie 除外:
sub vcl_recv {
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie,
";(SESS[a-z0-9]+|NO_CACHE)=", "; =");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
else {
return (pass);
}
}
}
此代码段将删除所有 cookie,除了与 SESS[a-z0-9]+|NO_CACHE
正则表达式匹配的那些。
使用vmod_cookie
在 Varnish 中有一种更简洁的 cookie 替换方法,它涉及使用 Varnish 中的 vmod_cookie
模块。您可以在这里找到它:https://github.com/varnishcache/varnish-cache/tree/master/lib/libvmod_cookie
如果升级到 Varnish 版本 6.4,vmod_cookie
将成为核心 Varnish 安装的一部分。
这相当于使用 vmod_cookie
:
vcl 4.1;
import cookie;
sub vcl_recv {
cookie.parse(req.http.cookie);
cookie.keep_re("SESS[a-z0-9]+,NO_CACHE");
set req.http.cookie = cookie.get_string();
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-54516992-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-54516992-1');
</script>
</head>
<body>
test
</body>
</html>
后端。这是 Python + Django。请不要害怕我只是在这里设置了一个 cookie (render_to_response),然后我需要一个在断点处停止的地方(在下面的代码中它通过注释显示在它所在的位置)。
class HomeView(TemplateView):
template_name = "home/home.html"
def render_to_response(self, context, **response_kwargs):
response = super(TemplateView, self).render_to_response(context, **response_kwargs)
response.set_cookie('sort_on', 'title')
return response
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context # Breakpoint.
varnishd 出于学习目的,我只是清理所有 cookie。
$ varnishd -V
varnishd (varnish-6.0.6 revision 29a1a8243dbef3d973aec28dc90403188c1dc8e7)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2019 Varnish Software AS
VCL
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
call remove_proprietary_cookies;
if (req.http.Cookie) {
return (pass);
}
}
sub remove_proprietary_cookies{
set req.http.Cookie = regsuball(req.http.Cookie, ".*", "");
}
然后我重新加载页面几次以使 cookie 确实存在。
在Chrome中:
document.cookie
"sort_on=title; _ga=GA1.1.988164671.1586849704; _gid=GA1.1.995393496.1586849704; _gat_gtag_UA_54516992_1=1"
饼干图片(以上文字的重复):
好的。我们检查过 Cookie 已设置。现在让我们检查cookie是否正确清理。
我在 braakpoint 停下来检查 cookie。值为 {}。
嗯。所有的饼干似乎都被清理了。
问题: 重新加载时,我不断地来到断点。这意味着 Varnish 将请求传递给后端。换句话说 if (req.http.Cookie) 没有像我预期的那样工作。我希望在上一步中我已经删除了 cookie。然后我检查 cookie 是否存在。而且不应该有任何。
你能帮帮我吗:
明白这是怎么回事了。
组织一切,这样如果我错误地删除了 cookie,我绝对应该删除它们。
使 Varnish 从缓存中处理此请求,而不将其传递到后端。
==============4 月 16 日添加================= ++++++++++++++++++++++++++++++++++++++++++++++++++++ +++
我已经将 Varnish 升级到 6.4:
michael@michael:~$ varnishd -V
varnishd (varnish-6.4.0 revision 13f137934ec1cf14af66baf7896311115ee35598)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2020 Varnish Software AS
我们要测试的内容:
- 在后端设置 Google 分析 cookie 和 cookie。
- 让 Varnish 删除所有 cookie 并缓存响应。
- 检查请求是否只传递到后端一次。
然后我在varnish后面组织了nginx(只是为了记录请求)。 Nginx 在 8090 监听。这是日志配置:
log_format main '[$time_local] $http_cookie';
Cookies:
- 在 HTML 中,我组织了 Google Analytics 的跟踪。
- 在后端,我将名为 "sort_on" 的 cookie 设置为值为 "title"。
+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++
如果我们不切饼干,日志看起来是这样的(这只是为了比较):
127.0.0.1 - - [16/Apr/2020:08:11:05 +0300] "GET / HTTP/1.1" sort_on=title; _ga=GA1.1.236170900.1587013419; _gid=GA1.1.2033785209.1587013419 200 334 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "127.0.0.1"
+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++
varnish.ctl
vcl 4.1;
import cookie;
backend default {
.host = "127.0.0.1";
.port = "8090";
}
sub vcl_recv {
unset req.http.Cookie;
if (req.http.Cookie) {
return (pass);
}
}
Nginx 将请求传递给后端。后端位于端口 8080。
总之听什么听哪里:
Varnish - 8000
Nginx - 8090
Backend - 8080
启动varnishd:
michael@michael:~$ sudo varnishd -f /home/michael/PycharmProjects/varnish/varnish.vcl -a localhost:8000
打开Chrome,多次加载页面:
Nginx的访问日志:
127.0.0.1 - - [16/Apr/2020:08:12:49 +0300] "GET / HTTP/1.1" - 200 334 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "127.0.0.1"
127.0.0.1 - - [16/Apr/2020:08:13:21 +0300] "GET / HTTP/1.1" - 200 334 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "127.0.0.1"
我们可以看到没有cookie。没关系。饼干被切断了。
问题: 请求不可避免地传递到后端。我总是在断点处停下来。
你能给我一些如何处理这个问题的建议吗?
Varnish 不会查看 Cookie
请求 header 的内容,而是检查 header 是否存在。
你需要做的是检查 Cookie
header 是否为空,如果是,则将其全部删除。
只需在您的 regsub
语句后添加:
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
使流程更灵活一些
实际上,您可能不会删除所有 cookie,而只会删除对您的应用程序来说不是必需的 cookie。
您可以使用此语句删除所有 cookie,但您的应用程序需要的 cookie 除外:
sub vcl_recv {
if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie,
";(SESS[a-z0-9]+|NO_CACHE)=", "; =");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
else {
return (pass);
}
}
}
此代码段将删除所有 cookie,除了与 SESS[a-z0-9]+|NO_CACHE
正则表达式匹配的那些。
使用vmod_cookie
在 Varnish 中有一种更简洁的 cookie 替换方法,它涉及使用 Varnish 中的 vmod_cookie
模块。您可以在这里找到它:https://github.com/varnishcache/varnish-cache/tree/master/lib/libvmod_cookie
如果升级到 Varnish 版本 6.4,vmod_cookie
将成为核心 Varnish 安装的一部分。
这相当于使用 vmod_cookie
:
vcl 4.1;
import cookie;
sub vcl_recv {
cookie.parse(req.http.cookie);
cookie.keep_re("SESS[a-z0-9]+,NO_CACHE");
set req.http.cookie = cookie.get_string();
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
}