Cookies

默认配置下,varnish不会缓存后端响应头中带有Set-Cookie的对象。当然,如果客户端发送的请求带有Cookie头,那么varnish将会忽略缓存,直接请求后端服务器。

这样可能过于保守。很多网站使用谷歌分析来分析他们的流量,谷歌分析会设置一个cookie来跟踪你。这个cookie被客户端的js所使用,服务端对其并不感兴趣。

来自客户端的cookie

对于很多web应用程序,忽略cookie也是有意义的,除非你访问的是网站的特殊部分。下面这段代码片段是在 vcl_recv 代码片段中会忽略cookie除非你访问的是 /admin/

if (!(req.url ~ "^/admin/")) {
    unset req.http.Cookie;
}

非常简单。但是,如果你需要做一些复杂的事情,例如移除几个cookie中的一个,事情就变得非常困难。可惜,varnish也没有好的工具去操作cookie。我们必须使用正则表达式来完成这样的工作。如果你熟悉正则表达式是怎么回事的话,你就会明白这些。如果你不了解这些的话,我们建议你看一本关于正则表达式的书,或者查看一些在线手册了解一下。

我们使用varnish Software(VS)这个网站来作为例子。非常简单的设置一下,varnish cache作为前端,后端使用Drupal based。VS使用谷歌分析来跟踪访问的cookie,还有一些其他一些类似的工具。这些cookie的设置和使用都是使用javascript。varnish和drupal不需要看这些cookie,所以我们可以在VCL中进程设置,使客户端发送这些cookie时,varnish将会忽略这些没有用的cookie。

下面的VCL,我们将会丢弃所有以下划线开头的cookie:

# Remove has_js and Google Analytics __* cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
# Remove a ";" prefix, if present.
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

让我们再看一个例子,我们移除叫做"COOKIE1"和"COOKIE2"以外的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, ";(COOKIE1|COOKIE2)=", "; \1=");
        set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
        set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

        if (req.http.Cookie == "") {
            unset req.http.Cookie;
        }
    }
}

下面是一个几乎可以实现相同功能的简单的例子。它是过滤掉所有其他的cookie,而不是从中挑选一个需要的cookie。然后将他复制到另外一个头中,然后再复制回请求头,删除原来的头。

sub vcl_recv {
    # save the original cookie header so we can mangle it
    set req.http.X-Varnish-PHP_SID = req.http.Cookie;
    # using a capturing sub pattern, extract the continuous string of
    # alphanumerics that immediately follows "PHPSESSID="
    set req.http.X-Varnish-PHP_SID =
       regsuball(req.http.X-Varnish-PHP_SID, ";? ?PHPSESSID=([a-zA-Z0-9]+)( |;| ;).*","\1");
    set req.http.Cookie = req.X-Varnish-PHP_SID;
    unset req.X-Varnish-PHP_SID;
}

在varnish cache wiki中还有更多例子。

来自后端服务器的cookie

如果你的后端服务器使用“Set-Cookie”头来设置一个cookie,在默认配置下,varnish将不会缓存这个页面。一个hit-for-pass的对象将会被创建。如果后端行为诡异,同时设置了一些不需要的cookie,只要unset这个“Set-Cookie”头,一切就好了。

Cache-Control

“Cache-Control”头指示缓存如何去处理内容。varnish关注“max-age”这个参数,并且使用它来计算一个对象的ttl。

因此,请确保你用max-age设置了Cache-Control头。你可以看看varnish software网站的drupal服务器的返回:

$ GET -Used http://www.varnish-software.com/|grep ^Cache-Control
Cache-Control: public, max-age=600

Age

varnish增加了一个“Age”的报头来表示对象在varnish中保存了多长时间。你可以使用varnishlog -I RespHeader:^Age来从varnishlog中筛选Age。

Pragma

一个HTTP 1.0服务器可能会发送一个“Pragma: nocache”的报头。varnish会忽略它,对于这个头信息你可以在vcl中很容易的添加支持。

vcl_backend_response中:

if (beresp.http.Pragma ~ "nocache") {
    set beresp.uncacheable = true;
    set beresp.ttl = 120s; # how long not to cache this url.
}

Authorization

如果varnish看到了一个“Authorization”头,它将会直接通过该请求。如果你不需要这个头,那么你可以unset。

覆盖time-to-live (TTL)

有的时候,你的后端服务器可能会出问题。在varnish中可以轻松的重写ttl,然后修复你的后端显示。

你需要VCL指定你想要的对象,然后你设置“beresp.ttl”:

sub vcl_backend_response {
    if (bereq.url ~ "^/legacy_broken_cms/") {
        set beresp.ttl = 5d;
    }
}

这个例子将会为你网站上旧的内容设置5天的ttl。

强制缓存某些请求和响应

但是你的后端可能还是有问题,仍然不能好好工作,你可能想要存放更多的资源到varnish。那么我们建议你依赖尽可能多的默认缓存规则。强制varnish在缓存中查找对象是容易的,但是我们并不推荐。

修正你的域名

有些网站有很多域名,http://www.varnish-software.com/http://varnish-software.com/http://varnishsoftware.com/ 都是指向同一网站。因为varnish并不知道他们是一样的,varnish将会为你的每一个域名缓存不同的版本和每一个页面。那么你可能需要设置重定向或者使用下面的VCL来缓解这种现象:

if (req.http.host ~ "(?i)^(www.)?varnish-?software.com") {
    set req.http.host = "varnish-software.com";
}

results matching ""

    No results matching ""