对于片断缓存,业界有成熟的解决方案,还有一个所谓的W3C标准:ESI(Edge Side Include) 。html
ESI自己没有什么,只是一个XML的标签集合。ESI和SSI(Server Side Include)很类似,作过ASP开发的都熟悉这么一个标签:前端
<!--#include src="header.inc" -->
IIS碰到这么一个标签后,会把header.inc里面的东西合并到当前的页面,这样作的好处是header.inc自己能够复用了,你能够在多个页面include它。web
ESI的功能也是相似的,只不过解析和合并它的任务通常落到缓存服务器或代理上:数据库
1: <esi:include src="/welcome" />
2: <ul>
3: #foreach($book in $books)
4: <li>$book.name</li>
5: #end
6: </ul>
好比对于上面这个片断,esi:include标签那里原本是应该显示特定于每一个用户的欢迎信息的,就由于这一点整个页面不能缓存太惋惜了。这个时候ESI粉墨登场。缓存服务器会将整个页面cache,而后它发现这儿有个ESI标签,它会根据src指定的地址去源服务器请求内容,而后将其合并到缓存的页面中,而后将完整的内容发送到客户端。整个过程相似下图所示:后端
这样咱们就不须要每次都去数据库查询那个图书列表了,由于图书列表可能更新的很缓慢。这样大大的下降了Web服务器的压力。浏览器
既然ESI是一个规范,那么确定有遵循这个规范的实现。好比大名鼎鼎的Squid就有支持ESI的模块。不过本文要介绍的是Varnish。Varnish是一个反向代理,使用缓存对HTTP加速,能够把它放到你的Web服务器的前面,对内容缓存,跟Squid的目的类似。不过由于Squid想干的事儿实在是太多,它已经再也不是一个纯粹的用户缓存加速的方向代理了,因此显得太过于臃肿,而比较起来Varnish更专一,更轻便。根据网站上的数据显示,Varnish表现出来的性能比Squid更好,并且占用的资源更少。缓存
下面我就简单的描述一下如何安装Varnish以及配置使用ESI。服务器
我是在Mac上安装Varnish的,从源代码编译过去的。基本上是一路命令下去,在configure的时候碰到缺乏libpcre,用port装上pcre就能够了:架构
1: $wget http://repo.varnish-cache.org/source/varnish-2.1.5.tar.gz
2: $tar zxvf varnish-2.1.5.tar.gz
3: $cd varnish-2.1.5
4: $sh autogen.sh
5: $sh configure
6: $make
7: $make install
根据环境不一样,可能缺乏一些依赖,我在安装的过程当中就缺乏libpcre。app
Varnish默认是安装在/usr/local/sbin目录下:varnishd。是daemo。
根据上面那幅图能够看出,Varnish并不本身提供服务,它只是做为一个缓存服务器。那么就必须有一个后端的服务器提供应用程序的服务。那咱们就须要让Varnish知道到哪儿去请求后端服务器。这个是经过配置文件设置的,Varnish的默认配置文件在/usr/local/etc/varish/default.vcl。
打开后咱们会发现一段被注释的代码,取消注释将其指向你的后端服务器(好比IIS):
1: backend default {
2: .host = "127.0.0.1";
3: .port = "8080";
4: }
配置好后,启动Varnish,而后去看看效果,启动的命令是:
1: sbin yuyi$sudo ./varnishd -a 0.0.0.0:80 -f /usr/local/etc/varnish/default.vcl -s malloc,500M
我简单的介绍下这几个选项,更详细的能够看man。
-a指定Varnish鉴定的地址。若是你的配置是上图所示,那么端口应该是80。若是你没有指定-a,那么默认配置使用/etc/services中的配置,通常状况下就是80。而-f指定配置文件的地址,默认状况下就是default.vcl,除非你想使用别的配置文件。
最有趣的是-s选项,它用来指定存储方式,以及缓存的大小。好比这里是malloc,那就是使用内存做为缓存,你还可使用file,使用磁盘做为缓存。后面是缓存大小,500兆。还能够指定K,G,T等,大小写均可以。
运行后咱们去浏览器打开http://127.0.0.1看看。为了测试你能够在页面输出一个DateTime.Now,而后刷新页面看看是否是每次都变化。
Varnish还有个不错的工具:varnishlog,打开后能够看到用户访问的一些状况。
好了,安装和简单配置就介绍这么多,那如何使用ESI呢?其实很简单,分为两个步骤,首先将你的页面上须要施加不一样缓存策略的片断切分,放到不一样的链接中。
好比原来你的首页混沌一片:有热点新闻板块、通知板块、还有广告以及显示用户登陆的板块。而它们原来极可能都是由index.aspx处理的。若是你想有针对性的对这些板块施加缓存策略,那么就应该将其独立开,使用不一样的链接(控制器)来处理:
1: <html>
2: <head>
3: <title>index</title>
4: </head>
5: <body>
6: <p>Welcome yuyijq</p>
7: <div>
8: <h3>Hot News</h3>
9: <ul>
10: <li>庆祝奥特曼45岁生日</li>
11: <li>拉登挂了</li>
12: </ul>
13: </div>
14: <div>
15: <h3>通知</3>
16: <ul>
17: <li>机房维护通知</li>
18: </ul>
19: </div>
20: </body>
21: <html>
如今咱们要拆分: hotnews->hotnews.aspx welcome->welcome.aspx
而后使用ESI标签分离:
1: <html>
2: <head>
3: <title>index</title>
4: </head>
5: <body>
6: <esi:include src="/welcome.aspx" />
7: <esi:include src="hotnews.aspx" />
8: <div>
9: <h3>通知</3>
10: <ul>
11: <li>机房维护通知</li>
12: </ul>
13: </div>
14: </body>
15: <html>
注意的是welcome.aspx和hotnews.aspx如今输出的是两个片断,不是完整的页面。
这些都准备好后,就是启用Varnish对ESI的处理了。
仍是编辑default.vcl文件。Varnish的配置能力很是强大,这个vcl是Varnish Configuration Language。刚才咱们仅仅是配置一个后端服务器,如今让咱们打开default.vcl仔细欣赏一下:
sub vcl_recv {
}
sub vcl_pipe {
}
sub vcl_pass {
}
sub vcl_hash {
}
sub vcl_hit {
}
sub vcl_miss {
}
sub vcl_fetch {
}
sub vcl_deliver {
}
sub vcl_error {
}
你会看到有vcl_recv,vcl_pipe,vcl_pass,vcl_hash,vcl_hit等函数。这些函数就表明一个请求进入Varnish所经过的阶段(参见这里)。就像一个管道同样,你能够在这些管道上作些自定义的处理。因此配置性很是强大。如今咱们只对vcl_fetch函数作一下简单修改:
sub vcl_fetch {
if(req.url == "/welcome.aspx"){
return (pass);
}
if (req.url == "/index.aspx") {
esi;
}
}
若是请求的url是/welcome.aspx就直接pass,也就是不作任何处理,请求直接递交给后端应用服务器(IIS)。若是请求是/index.aspx,也就是咱们上面列出的那个包含esi标签的页面,就对其进行ESI处理,这样Varnish就会解析这个页面,看看缓存中有没有,若是有的话则从缓存中取出页面,并将其与从后端服务器获取的welcome.aspx片断合并,而后直接发送回请求。
用Varnish处理ESI就这么简单,不过使用Varnish以前咱们还得对其某些参数进行配置,好比缓存多长时间啊等等。默认状况下Varnish会缓存120秒,你能够经过管理功能对其进行配置,还能够经过在vcl里对某些模块进行精细的控制。
还记得咱们是怎样启动Varnish的么,若是在启动参数里加上-T 127.0.0.1:5000,那么咱们就可使用telnet对Varnish进行管理了。咱们只须要telnet上这个端口,而后可使用不少丰富的命令了,更多细节留给你尝试吧。
前一篇文章介绍的使用Velocity自定义标签来实现片断缓存和这一篇介绍的使用ESI都有本身的优缺点。
使用Velocity自定义标签的方案工做在应用程序这一层,这样开发人员有最大的控制权力,并且实现起来也比较简单,所使用的也都是你们都熟悉的技术,但问题是它仍是由应用程序服务器来处理得,能够说它减轻了一部分应用程序服务器和数据库服务器的压力,但还有一部分压力仍是须要它来承担,并且在应用程序中解决所使用的缓存一定是和应用程序所采用的缓存机制同样(固然你也能够为此独立使用一个缓存),对缓存服务器也有部分压力。
而使用ESI的方案,它须要运维团队的配置,甚至须要修改服务器配置的架构(添加了前端服务器),若是在多部门协调比较困难的项目中,这种方案还会遇到一些阻力。
可是它带来的好处确实显而易见的。首先ESI是一个W3C标准,我更倾向于采用标准的作法。并且Varnish这样的方向代理,它原本就擅长这个,它能够彻底把这部分压力从应用程序服务器和缓存服务器上接管过来,并且会处理的更出色。
因而可知什么方案都是须要权衡各方利弊,获得一个平衡的效果啊。