取消和删除缓存

增大缓存对象的TTL(time-to-live ),是增加命中率的其中一种非常有效的方式。但是,你应该也有所了解,对有些网站(像Twitter这样的社交网站),服务内容过于陈旧对企业是不利的。

对于这个问题的解决方案就是当内容有更新的时候通知Varnish。有三种机制可以做到这一点。HTTP方式的清除缓存,命令行方式的删除缓存和强制命中但不缓存。我们先看看HTTP方式的清除缓存。

HTTP方式清除缓存

purge 就是从缓存中选中一个对象,然后删除它和它相关的内容。通常这个操作是通过调用HTTP协议的PURGE的方法来完成的。

HTTP purge和HTTP的GET请求很相似,不同的是HTTP请求的方法是`PURGE`。其实你可以自己定义这个方法名,不一定要用`PUGRE`,但是很多人习惯用这个名字。比如说Squid,它也支持同样的机制。 为了让Varnish支持HTTP方式清除缓存,在你的VCL中需要作如下配置::

acl purge {
        "localhost";
        "192.168.55.0"/24;
}

sub vcl_recv {
        # allow PURGE from localhost and 192.168.55...

        if (req.method == "PURGE") {
                if (!client.ip ~ purge) {
                        return(synth(405,"Not allowed."));
                }
                return (purge);
        }
}

如你所见,这里我们用了一个新的操作–return(purge)。在vcl_recv执行的最后的一步是跳到vcl_hash。这看起来像是在处理一个常规请求一样。但是当vcl_hash调用return(lookup)的时候Varnish会清除对象然后调用vcl_purge。在这里你可以在参数选项中指定任何你想让Varnish去删除的对象的详细信息。

比如你想删除example.com的首页,你必须发出这样的请求:

PURGE / HTTP/1.0
Host: example.com

Varnish接收请求之后会丢弃首页的内容。Varnish会删除HTTP的Vary头部中定义的相关全部内容。

取消缓存

还有另外一种去掉缓存的方式是:取消缓存。你可以把 “取消缓存”理解为对已经缓存的对象的一种过滤器。你可以从你的缓存中把某些内容``取消缓存``。你可以基于任何已有的元数据把具体内容取消缓存。取消缓存只对那些已经被缓存的对象有效,对新增加的对象和正在处理的对象是无效的。

取消缓存是Varnish内置的功能,只能在Varnish的命令行接口(CLI)执行。如果我想对example.com域名下的所有.png后缀的对象取消缓存,这种情况下可以执行下面的命令:

ban req.http.host == "example.com" && req.url ~ "\.png$"

功能真的非常强大。

当我们缓存一个对象的时候,需要选择一个取消缓存规则。但是在返回数据给客户端之前 一个对象只会匹配最新的取消缓存规则.

取消缓存规则在匹配`obj.*`这类对象的时候,也会通过一个叫做作`ban lurker`的后台进程处理。ban lurker`会将对象放到堆栈中并尝试匹配这些对象,然后从堆栈中删除匹配的对象。值得高兴的是`ban lurker`可以通‘ban_lurker_sleep’来控制。也可以通过将参数‘ban_lurker_sleep’设置为0来关闭`ban lurker

如果取消缓存规则比缓存中缓存时间最长的对象都陈旧,它就会直接被删除了。如果你的很多对象的TTL值设置的很大,而且不经常被访问,你可能会积累了很多取消缓存规则。这可能会增加CPU的使用率从而影响性能。

你也可以通过HTTP添加取消缓存规则。要做到这点你需要配置VCL:

sub vcl_recv {
        if (req.method == "BAN") {
                # Same ACL check as above:
                if (!client.ip ~ purge) {
                        return(synth(403, "Not allowed."));
                }
                ban("req.http.host == " + req.http.host +
                      " && req.url == " + req.url);

                # Throw a synthetic page so the
                # request won't go to the backend.
                return(synth(200, "Ban added"));
        }
}

这段VCL配置是让Varnish能处理一个HTTP的BAN方法,对请求的URL包括域名添加取消缓存规则。

ban lurker`可以帮助你保持取消缓存规则列表在一个可管理的大小范围,所以我们建议你在取消缓存规则中避免使用 `req.*,因为这种请求对象对于`ban lurker`是无效的。

你可以使用下面的模板让取消缓存规则对于`ban lurker`更加友好:

sub vcl_backend_response {
  set beresp.http.x-url = bereq.url;
}

sub vcl_deliver {
  unset resp.http.x-url; # Optional
}

sub vcl_recv {
  if (req.method == "PURGE") {
    if (client.ip !~ purge) {
      return(synth(403, "Not allowed"));
    }
    ban("obj.http.x-url ~ " + req.url); # Assumes req.url is a regex. This might be a bit too simple
  }
}

想要查看当前的取消缓存规则列表,请在命令行接口(CLI)中执行``ban.list``命令。这个命令会返回当前的取消缓存规则列表中所有取消缓存规则的状态:

0xb75096d0 1318329475.377475    10      obj.http.x-url ~ test
0xb7509610 1318329470.785875    20G     obj.http.x-url ~ test

这个取消缓存规则列表包含取消缓存规则的ID和创建取消缓存规则的时间戳。中间一列是当前已经被取消缓存的对象的总数,如果这个数值后面有个‘G’表示这个取消缓存规则已经失效了。最后列出的取消缓存规则列表中有些重复的取消缓存规则也会标记为‘G’,为了以后优化,这种取消缓存规则也会保存在列表中。

强制命中但不缓存

最后一种删除缓存更新对象内容的方法是在单个请求中强制 hash miss。如果你设置 ‘req.hash_always_miss’为true,Varnish将不会在缓存中查找当前对象,直接强制从后端服务器获取内容。这样就会返回给客户端最新的内容,替代当前缓存中的内容。缓存中的旧的内容会一直留在缓存中直到TTL过期,或者被其他一些机制删除。

Table Of Contents

This Page