开发者社区> 余二五> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

●Achiveving a high hitrate(提高缓存命中率)

简介:
+关注继续查看
         Achiveving a high hitrate(提高缓存命中率)
                   现在varnish已经正常运行了,您可以通过varnish访问到您的web应用程序。如果您的web程序在设计时候没有考虑到加速器的架构,那么您可能有必要修改您的应用程序或者varnish配置文件,来提高varnish的命中率。
                   既然这样,您就需要一个工具用来观察您和web服务器之间HTTP头信息。服务器端您可以轻松的使用varnish的工具,比如varnishlogvarnishtop,但是客户端的工具需要您自己去准备,下面是我经常使用的工具。
         Varnistop
                   您可以使用varnishtop确定哪些URL经常命中后端。Varnishtop –i txurl 就是一个基本的命令。您可以通过阅读“Statistics”了解其他示例。
         Varnishlog
                  当您需要鉴定哪个URL被频繁的发送到后端服务器,您可以通过varnishlog对请求做一个全面的分析。varnishlog –c –o /foo/bar 这个命令将告诉您所有(-o)包含”/football/bar”字段来自客户端(-c)的请求。
         Lwp-request
                   Lwp-requestwww库的一部分,使用perl语言编写。它是一个真正的基本程序,它可以执行HTTP请求,并给您返回结果。我主要使用两个程序,GETHEAD
                   Vg.no是第一个使用varnish的站点,他们使用varnish相当完整,所以我们来看看他们的HTTP 头文件。我们使用GET请求他们的主页:
                   $ GET -H 'Host: www.vg.no' -Used http://vg.no/
GET http://vg.no/
Host: www.vg.no
User-Agent: lwp-request/5.834 libwww-perl/5.834
 
200 OK
Cache-Control: must-revalidate
Refresh: 600
Title: VG Nett - Forsiden - VG Nett
X-Age: 463
X-Cache: HIT
X-Rick-Would-Never: Let you down
X-VG-Korken: http://www.youtube.com/watch?v=Fcj8CnD5188
X-VG-WebCache: joanie
X-VG-WebServer: leon
OK,我们来分析它做了什么。GET 通过发送HTTP 0.9的请求,它没有主机头,所以我需要添加一个主机头使用-H选项,-U打印请求的头,-s打印返回状态,-e 答应返回状态的头,-d 丢弃当前的连接。我们正真关心的不是连接,而是头文件。
如您所见VG的头文件中有相当多的信息,比如 X-RICK-WOULD-NEVERvg.no定制的信息,他们有几分奇怪的幽默感。其他的内容,比如X-VG-WEBCACHE 是用来调试错误的。
核对一个站点是否使用cookies,可以使用下面的命令:
GET -Used http://example.com/ |grep ^Set-Cookie
Live HTTP Headers
这是一个firefox的插件,live HTTP headers 可以查看您发送的和接收的http头。软件在https://addons.mozilla.org/en-US/firefox/addon/3829/下载。或者googleLive HTTP headers”。
The Role of HTTP headers
Varnish认为自己是真正的web服务器,因为它属于您控制。IETF没有真正定义surrogate origin cache 角色的含义,(The role of surrogate origin cache is not really well defined by the IETF so RFC 2616 doesn’t always tell us what we should do.不知如何翻译)
Cache-Control
Cache-control指示缓存如何处理内容,varnish关心max-age参数,并使用这个参数计算每个对象的TTL值。
cache-controlnocache 这个参数已经被忽略,不过您可以很容易的使它生效。
在头信息中控制cache-controlmax-age,您可以参照下面,varnish软件管理服务器的例子:
$ GET -Used http://www.varnish-software.com/|grep ^Cache-Control
Cache-Control: public, max-age=600
Age
Varnish添加了一个age头信息,用来指示对象已经被保存在varnish中多长时间了。您可以在varnish中找到Age信息:
         varnishlog -i TxHeader -I ^Age
Overriding the time-to-livettl
有时候后端服务器会当掉,也许是您的配置问题,很容易修复。不过更简单的方法是修改您的ttl,能在某种程度上修复难处理的后端。
         您需要在VCL中使用beresp.ttl定义您需要修改的对象的TTL
sub vcl_fetch {
    if (req.url ~ "^/legacy_broken_cms/") {
        set beresp.ttl = 5d;
    }
}
         Cookies
现在Varnish接收到后端服务器返回的头信息中有Set-Cookie信息的话,将不缓存。所以当客户端发送一个Cookie头的话,varnish将直接忽略缓存,发送到后端服务器。
这样的话有点过度的保守,很多站点使用Google AnalyticsGA)来分析他们的流量。GA设置一个cookie跟踪您,这个cookie是客户端上的一个java 脚本,因此他们对服务器不感兴趣。
对于一个web站点来说,忽略一般cookies是有道理的,除非您是访问一些关键部分。这个VCLvcl_recv片段将忽略cookies,除非您正在访问/admin/
 
 
if ( !( req.url ~ ^/admin/) ) {
  unset http.Cookie;
}
很简单,不管您需要做多么复杂的事情,比如您要删除一个cookies,这个事情很困难,varnish也没有相应的工具来处理,但是我们可以使用正则表达式来完成这个工作,如果您熟悉正则表达式,您将明白接下来的工作,如果您不会我建议您找找相关资料学习一下。
我们来看看varnish软件是怎么工作的,我们使用一些GA和一些相似的工具产生cookies。所有的cookies使用jsp语言。Varnish和企业网站不需要这些cookies,而varnish会因为这些cookies而降低命中率,我们将放弃这些多余的cookies,使用VCL
下面的VCL将会丢弃所有被匹配的cookies
// 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 = regsuball(req.http.Cookie, "^;\s*", "");
下面的例子将删除所有名字叫COOKIE1COOKIE2cookies
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 == "") {
        remove req.http.Cookie;
    }
}
这个例子是来自varnish wiki的。
         Vary
                   各式各样的头被发送到web server,他们让HTTP目标多样化。Accept-Encoding头就有这种感觉,当一个服务器分发一个“VaryAccept-Encoding”给 varnishVarnish需要cache来自客户端的每个不同的Accept-Encoding。如果客户端只接收gzip编码,varnish不对其他编码服务,那么就可以缩减编码量。
                   问题就是这样的,Accept-Encoding字段包含很多编码方式,下面是不同浏览器发送的:
                   Accept-Encodign: gzip,deflate
                   另一个浏览器发送的:
                   Accept-Encoding:: deflate, gzip
                   Varnish可以使两个不同的accept-enconding头标准化,这样就可以尽量减少变体。下面的VCL代码可以是accept-encoding头标准化:
 
 
 
 
 
 
if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
        # No point in compressing these
        remove req.http.Accept-Encoding;
    } elsif (req.http.Accept-Encoding ~ "gzip") {
        set req.http.Accept-Encoding = "gzip";
    } elsif (req.http.Accept-Encoding ~ "deflate") {
        set req.http.Accept-Encoding = "deflate";
    } else {
        # unkown algorithm
        remove req.http.Accept-Encoding;
    }
}
这段代码设置客客户端发送的accept-encoding头只有gzipdefault两种编码,gzip优先。
         Pitfall – VaryUser-Agent
                   一些应用或者一些应用服务器发送不同user-agent头信息,这让varnish为每个单独的用户保存一个单独的信息,这样的信息很多。一个版本相同的浏览器在不同的操作系统上也会产生最少10种不同的user-agent头信息。如果您想通过基于user-agent的修改,让他们标准化,您的命中率将收到严重的打击。
         Pragma
                   http 1.0 服务器可能会发送“Pragmanocache”。 Varnish忽略这个头,您可以轻松的使用VCL来完成这个任务:
                   In vcl_fetch
if (beresp.http.Pragma ~ "nocache") {
   pass;
}
         Authorization
                   如果varnish收到一个认证请求的头,他将pass这个请求,如果您不打算对这个头做任何操作的话。
         Normalizing your namespace
有些站点访问的主机名有很多,比如http://www.varnish-software.comhttp://varnish-software.comhttp://varnishsoftware.com  所有的地址都对应相同的一个站点。但是varnish不知道,varnish会缓存每个地址的每个页面。您可以减少这种情况,通过修改web配置文件或者通过以下VCL
if (req.http.host ~ "^(www.)?varnish-?software.com") {
  set req.http.host = "varnish-software.com";
}
         Purging
增加TTL值是提高命令率的一个好方法,如果用户访问到的内容是旧的,这样就会对您的商务照成影响。
解决方法就是当有新内容提供的时候通知varnish。可以通过两种机制HTTP purgingbans。首先,我们来看一个清理的实例:
 
         HTTP purges
                   HTTP purgesHTTP GET请求相似,除了这是用来purges的。事实上您可以在任何您喜欢的时间使用这个方法,但是大多数人使用它purgingSquid支持相同的机制,为了让varnish支持purging,您需要在VCL中做如下配置:
acl purge {
        "localhost";
        "192.168.55.0/24";
}
 
sub vcl_recv {
        # allow PURGE from localhost and 192.168.55...
 
        if (req.request == "PURGE") {
                if (!client.ip ~ purge) {
                        error 405 "Not allowed.";
                }
                return (lookup);
        }
}
 
sub vcl_hit {
        if (req.request == "PURGE") {
                # Note that setting ttl to 0 is magical.
                # the object is zapped from cache.
                set obj.ttl = 0s;
                error 200 "Purged.";
        }
}
 
sub vcl_miss {
        if (req.request == "PURGE") {
 
                error 404 "Not in cache.";
        }
}
您可以看见,使用了新的VCL子程序,vcl_hitvcl_miss。当您调用lookup时将在缓存中查找目标,结果只会是miss或者hit,然后对应的子程序就会被调用,如果vcl_hit的目标存储在缓存中,并且可用,我们可以修改TTL值。
所以对于vg.no 的无效首页,他们使用varnish做如下处理:
PURGE / HTTP/1.0
Host: vg.no
如果varnish想要丢弃主页,如是很多相同URL的变体在cache中,只有匹配的变体才会被清除。清除一个相同页面的gzip变体可以使用下面命令:
                  
PURGE / HTTP/1.0
Host: vg.no
Accept-Encoding: gzip
         Bans
这是另外一种清空无效内容的方法,bans。您可以认为bans是一种过滤方法,您可以禁止某些存在cache中存在的数据。您可以基于我们拥有的元数据来禁止。
                   Varnish内置的CLI接口就是支持bans的。禁止vg网站上的所有png目标代码如下:
                   purge req.http.host == "vg.no" && req.http.url ~ "\.png$"
                   是不是很强大?
                   在没有被bans命中之前的cache,是能够提供服务的。一个目标只被最新的bans检查。如果您有很多长TTL的目标在缓存中,您需要知道执行很多的Bans对性能照成的影响。
                   您也可以在varnish中添加bans,这样做需要一点VCL
sub vcl_recv {
        if (req.request == "BAN") {
                # Same ACL check as above:
                if (!client.ip ~ purge) {
                        error 405 "Not allowed.";
                }
                purge("req.http.host == " req.http.host
                      "&& req.url == " req.url);
 
                # Throw a synthetic page so the
                # request wont go to the backend.
                error 200 "Ban added"
        }
}
这是一个实用varnishVCL处理ban的方法。添加一个banURL上,包含它的主机部分。




本文转自 fenghao.cn 51CTO博客,原文链接:http://blog.51cto.com/linuxguest/360515,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Hibernate的一级缓存
缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取.
25 0
Struts2+Spring+Hibernate整合步骤
Struts2+Spring+Hibernate是J2EE的最新流行框架。本篇是我搭建这个框架的经验总结。 本方案采用自底向上:Hibernate——>Spring——>Struts2的方式进行整合。具体步骤如下: 1.通过MyEclipse向导,导入实现Hibernate3.2功能:生成会话工厂和hibernate.cfg.xml文件。然后在src中添加log4j.properties文件。 2.通过MyEclipse向导,导入实现Spring2.5功能,生成applicationContext.xml文件。然后将Spring2.0 AOP Liberaries里的asm2.2.3.jar包
42 0
Hibernate 一二级缓存
一级缓存(默认开启),Session缓存,会话级缓存 生命周期:就是session的生命周期,从session创建到session销毁。 一级缓存中的数据使用范围在当前session范围之内 实体类的三种状态 瞬时态 -> save() 对象里面没有id值,对象与session没有关联 持久态 ->get() 对象里面有id值,对象与session有关联 托管态 对象里面有id值,对象与session没有关联 什么是缓存 数据存到数据库里面,数据库本身就是文件系统,使用流方式操作文件效率不是很高。
953 0
Hibernate-03-核心api
1.Configuration Configuration 2.SessionFactory(重点) SessionFactory Utils工具类:只在类被定义的时候创建sessionFactory,保证sessionFactory只被创建一次 Utils工具类 3.
637 0
spring4+hibernate4+struts2项目整合的步骤及注意事项
  首先,在整合框架之前,我们需要知道Spring框架在普通Java project和Web project中是略有不同的.   这个不同地方就在于创建IOC容器实例的方式不同,在普通java工程中,可以在main方法中直接创建,可是web工程就不一样了,在Web项目工程中应该在服务器加载时就创建IOC容器.
844 0
Hibernate中使用@Lob 注解保存String[] 问题
Hibernate中使用@Lob 注解保存String[] 问题 在Hibernate注解中如何你想保存一个字段为String数组类型,如果你想尝试保存为clob类型的话,一般情况下为定义为: @Entity Public class Person { … @Lob String[] stringArray; ….
1017 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载