随着公司站点访问量的上升,公司近期决定再增加两个squid节点,初建CDN雏形。所以在启用其他squid的节点之前,想对目前在用的一台squid的命中率再进行下优化。由于前期规划比较到位,动静应用进行了很好的分离。几乎所有的图片、js、css、html等文件都走一个单独的域名,而其他动态应用使用图片、css、js等文件时,会调用到该域名。所以之前的squid的主要配置部分——refresh_pattern参数部分直接使用的默认配置命中率就在90%以上(动态页面不走squid,但动态页面里调用的静态内容走squid,所以命中率会非常高)。

目前的站点架构是 nginx入口———— squid反向代理————nginx静态配置与动态反向代理————tomcat应用。在开启后端nginx的access日志后,发现后端日志中有已经缓存过的静态文件的日志,而http代码为304。这就感觉有点奇怪了。即然已经前端有squid了,如果squid里面没有的,会到后端真实服务器上去取,返回状态码应该是200或40X才对啊。开始使用chrome 对页面进行访问分析,按F12或右键-审核元素(当然firefox的firebug、IE下的httpwatch、IE9按F12自该的开发工具等都非常优秀)。

如下图所示,一个为第一次访问时的分析图 ———— hit命中,另一张图为F5刷新时的分析图 ———— MISS未命中。

squid-200-hit squid-304-miss

造成该问题的原因为:每一次刷新页面时,squid都要和后端机器通信,检查资源是否被修改。解决该问题可以使用ignonre-reload参数,该参数的作用是忽略客户端 no-cache 或 reload 头,不过这是违反 HTTP 标准的做法。使用该参数后refresh_pattern部分的配置如下:

1refresh_pattern ^ftp:           1440    20%     10080
2refresh_pattern ^gopher:        1440    0%      1440
3refresh_pattern -i (/cgi-bin/|?) 0     0%      0
4refresh_pattern -i .              0     50%     4320  ignore-reload 

但这样配置以后也有问题,编辑部的相关人员更新过html、js、css相关文件以后,通过刷新和强制刷新以后,发现页面并不能更新。而早上更新过的文件,到中午还不见有变化(会变化才怪,缓存的最大超时时间是3天,而且有了ignonre-reload参数以后,刷新和强制刷新又会被忽略掉,只能等待缓存时间超期,squid重新从后端检测)。于是又将上面的配置文件修改为:

 1refresh_pattern ^ftp:           1440    20%     10080
 2refresh_pattern ^gopher:        1440    0%      1440
 3refresh_pattern -i (/cgi-bin/|?) 0     0%      0
 4refresh_pattern -i .gif$         0     50%     4320 ignore-reload
 5refresh_pattern -i .bmp$         0     50%     4320 ignore-reload
 6refresh_pattern -i .jpg$         0     50%     4320 ignore-reload
 7refresh_pattern -i .png$         0     50%     4320 ignore-reload
 8refresh_pattern -i .swf$         0     50%     4320 ignore-reload
 9refresh_pattern -i .mp3$         0     50%     4320 ignore-reload
10refresh_pattern -i .wmv$         0     50%     4320 ignore-reload
11refresh_pattern -i .rm$          0     50%     4320 ignore-reload
12refresh_pattern -i .mpeg$        0     50%     4320 ignore-reload
13refresh_pattern -i .wma$         0     50%     4320 ignore-reload
14refresh_pattern -i (jquery(.*).js$)    0       20%     4320  ignore-reload
15refresh_pattern -i .              0     50%     4320   

对图片和视频文件使用ignore-reload参数,对第三方的jquery提供的js文件也使用ignore-reload参数。像其他js、css、html文件不使用ignore-reload参数,这样编辑部的人再刷新页面时就自动去后端检测并在页面变化时自动更新squid缓存。

但此时还存在一个问题,在图片有更新时,此时还会从squid缓存里拿老的。此时就要借助squidclient工具强制移除后端文件了,不过每次都利用squidclient工具让运维人员来操作也挺麻烦。回头再利用cgi、php、jsp等文件来做一个web页面,这样输入提交,在squid服务器上自动移除旧的缓存文件。