转载请注明原文链接:http://blog.csdn.net/omohe/archive/2009/07/09/4335765.aspx
版本:v1.0 作者:OMO 最后修改时间:2009.07.09
前端的lvs和squid,按照安装方法,把epoll打开,配置文件照搬,基本上问题不多。
这个架构和app_squid架构的区别,也是关键点就是:加入了一级中层代理,中层代理的好处实在太多了:
1、gzip压缩
压缩可以通过nginx做,这样,后台应用服务器不管是apache、resin、lighttpd甚至iis或其他古怪服务器,都不用考虑压缩的功能问题。
2、负载均衡和故障屏蔽
nginx可以作为负载均衡代理使用,并有故障屏蔽功能,这样,根据目录甚至一个正则表达式来制定负载均衡策略变成了小case。
3、方便的运维管理,在各种情况下可以灵活制订方案。
例如,如果有人用轻量级的ddos穿透squid进行攻击,可以在中层代理想办法处理掉;访问量和后台负载突变时,可以随时把一个域名或一个目录的请求扔入二级cache服务器;可以很容易地控制no-cache和expires等header。等等功能。。。
4、权限清晰
这台机器就是不写程序的维护人员负责,程序员一般不需要管理这台机器,这样假如出现故障,很容易能找到正确的人。
对于应用服务器和数据库服务器,最好是从维护人员的视线中消失,我的目标是,这些服务只要能跑得起来就可以了,其它的事情全部可以在外部处理掉。
一、squid及web缓存介绍
Squid是一种用来缓冲Internet数据的软件。它是这样实现其功能的,接受来自人们需要下载的目标(object的请求并适当地处理这些请求。也就是说,如果一个人想下载一web页面,他请求Squid为他取得这个页面。Squid随之连接到远程服务器(比如:http://squid.nlanr.net/)并向这个页面发出请求。然后,Squid将web端得到的数据转发给客户端机器,而且同时复制一份,当下一次有人需要同一页面时,Squid可以简单地从磁盘中读到它,那样数据迅即就会传输到客户机上。当前的Squid可以处理HTTP,FTP,GOPHER,SSL和WAIS等协议。但它不能处理如POP,NNTP,RealAudio以及其它类型的东西。
cache命中在squid每次从它的缓存里满足HTTP请求时发生。cache命中率,是所有HTTP请求中命中的比例。Web缓存典型的cache命中率在30%到60%之间。另一个相似的度量单位叫做字节命中率,描绘了cache提供服务的数据容量(字节数)。
cache丢失在squid不能从它的缓存里满足HTTP请求时发生。cache丢失的理由有很多种。最明显的,当squid第一次接受到对特殊资源的请求时,就是一个cache丢失。类似的情况是,squid会清除缓存以释放空间给新对象。另外的可能是资源不可到达。原始服务器会指示cache怎样处理响应。例如,它会提示数据不能被缓存,或在有限的时间内才被重复使用,等等。
cache确认保证squid不对用户返回过时数据。在重复使用缓存对象时,squid经常从原始服务器确认它。假如服务器指示squid的拷贝仍然有效,数据就发送出去。否则,squid升级它的缓存拷贝,并且转发给客户。
二、系统环境
两台web缓存服务器安装CentOS 5.8+squid+memcached,分别命名为squid_cache1和squid_cache2。Squid对于后端的web服务器没有要求,可以是IIS,也可以是apache或是其他的。缓存前端可以有一层负载均衡,如果是LVS的话,那么两台缓存服务器都需要绑定VIP。
Squid_cache1:
Ip:192.168.0.149
子网掩码:255.255.255.0
默认网关:192.168.0.1
Squid_cache2:
Ip:192.168.0.150
子网掩码:255.255.255.0
默认网关:192.168.0.1
- SELINUX=disabled #修改
- #SELINUXTYPE=targeted #注释掉
- net.ipv4.tcp_rmem = 4096 87380 4194304
- net.ipv4.tcp_wmem = 4096 65536 4194304
- net.core.wmem_default = 8388608
- net.core.rmem_default = 8388608
- net.core.rmem_max = 16777216
- net.core.wmem_max = 16777216
- net.core.netdev_max_backlog = 262144
- net.core.somaxconn = 262144
- net.ipv4.tcp_max_orphans = 3276800
- net.ipv4.tcp_max_syn_backlog = 8192
- net.ipv4.tcp_max_tw_buckets = 5000
- net.ipv4.tcp_timestamps = 0
- net.ipv4.tcp_synack_retries = 1
- net.ipv4.tcp_syn_retries = 1
- net.ipv4.tcp_tw_recycle = 1
- net.ipv4.tcp_tw_reuse = 1
- net.ipv4.tcp_mem = 786432 1048576 1572864
- net.ipv4.tcp_fin_timeout = 30
- net.ipv4.tcp_keepalive_time = 1200
- net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_rmem = 4096 87380 4194304:TCP读buffer,可参考的优化值: 32768 436600 873200
net.ipv4.tcp_wmem = 4096 65536 4194304:TCP写buffer,可参考的优化值: 8192 436600 873200
net.core.wmem_default:表示发送套接字缓冲区大小的缺省值(以字节为单位)
net.ipv4.tcp_tw_recycle = 1:表示开启TCP连接中TIME-WAIT sockets的快速回收。
net.ipv4.tcp_tw_reuse = 1:表示开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接。
ulimit -n #查看当前用户的文件描述符的限制数目
- * hard nofile 4096
- * soft nofile 4096
- #define __FD_SETSIZE 4096
- #define __FD_SETSIZE 4096
cat /proc/sys/net/ipv4/ip_local_port_range #查看分配的本地端口范围
echo "1024 65000" > /proc/sys/net/ipv4/ip_local_port_range #修改端口范围
- echo "1024 65000" > /proc/sys/net/ipv4/ip_local_port_range
- 1 5 * * * /usr/sbin/ntpdate time.nist.gov
- -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
wget http://cloud.github.com/downloads/libevent/libevent/libevent-2.0.19-stable.tar.gz
wget http://memcached.googlecode.com/files/memcached-1.4.13.tar.gz
wget http://www.squid-cache.org/Versions/v3/3.1/squid-3.1.20-20120610-r10455.tar.gz
配置文件如下
http_port 59.175.238.60:80 defaultsite=219.140.171.194 vhost vport=80
cache_mem 2048 MB
cache_swap_low 90
cache_swap_high 95
maximum_object_size 20 MB
maximum_object_size_in_memory 8 MB
cache_dir ufs /squid_cache 100000 128 512
cache_peer 219.140.171.194 parent 80 0 no-query originserver
cache_peer_domain 219.140.171.194 img.cnhubei.com
acl all src 0.0.0.0/0.0.0.0
acl Safe_ports port 80
acl Safe_ports port 443
acl AntiBaidu req_header User-Agent Baiduspider
acl cnhubei referer_regex -i cnhubei
acl nullref referer_regex -i ^$
http_access allow nullref
http_access deny !Safe_ports
http_access deny AntiBaidu
http_access deny !cnhubei
deny_info http://www.cnhubei.com/images/2007cnhubei04y002.jpg cnhubei
http_access allow all
visible_hostname www.w3cool.com
cache_mgr [email protected]
#### Disable Logs
cache_store_log none
cache_vary on
logfile_rotate 0
refresh_pattern -i \.*$ 1440 90% 129600 reload-into-ims
参数设置的都很暴力,还设置了一个反盗链
其实主要就是refresh_pattern的一些理解和建议.
概念LM,LM就是页面Header里时间(Date)和Last-Modified时间的差。Date一般是Squid从后面取页面的时间,Last-Modified 一般是页面生成时间。
refresh_pattern 的语法是
refresh_pattern [-i] regexp min percent max [options]
min, max的单位是分钟,percent就是百分比。
refresh_pattern 的算法如下:(当前时间定义为CURRENT_DATE)
1) If ((CURRENT_DATE-DATE(就是LM里定义的时间)) < min),cache是新鲜的
2) else if ((CURRENT_DATE-DATE) < (min + (max-min)*percent),cache是新鲜的
3) else cache是过期的
cache过期就需要从后面server取新鲜内容。
常用的几个参数的意思
override-expire
该选项导致squid在检查Expires头部之前,先检查min值。这样,一个非零的min时间让squid返回一个未确认的cache命中,即使该响应准备过期。
override-lastmod
改选项导致squid在检查LM-factor百分比之前先检查min值。
reload-into-ims
该选项让squid在确认请求里,以no-cache指令传送一个请求。换句话说,squid在转发请求之前,对该请求增加一个If-Modified- Since头部。注意这点仅仅在目标有Last-Modified时间戳时才能工作。外面进来的请求保留no-cache指令,以便它到达原始服务器。
一般情况可以使用 reload-into-ims。它其实是强行控制对象的超时时间,这违反了http协议的精神,但是在带宽较窄的场合,可以提高明显系统相应时间。
举例:
refresh_pattern -i \.css$ 1440 50% 129600 reload-into-ims
refresh_pattern -i \.xml$ 1440 50% 129600 reload-into-ims
refresh_pattern -i \.html$ 1440 90% 129600 reload-into-ims-
refresh_pattern -i \.shtml$ 1440 90% 129600 reload-into-ims
refresh_pattern -i \.hml$ 1440 90% 129600 reload-into-ims
refresh_pattern -i \.jpg$ 1440 90% 129600 reload-into-ims
refresh_pattern -i \.png$ 1440 90% 129600 reload-into-ims
refresh_pattern -i \.gif$ 1440 90% 129600 ignore-reload
refresh_pattern -i \.bmp$ 1440 90% 129600 reload-into-ims
refresh_pattern -i \.js$ 1440 90% 129600 reload-into-ims
ignore-reload
该选项导致squid忽略请求里的任何no-cache指令。
所以。如果希望内容一进入cache就不删除,直到被主动purge掉为止,可以加上ignore-reload选项,这个我们常用在mp3,wma,wmv,gif之类。
Examples:
refresh_pattern -i \.mp3$ 1440 50% 2880 ignore-reload
refresh_pattern -i \.wmv$ 1440 50% 2880 ignore-reload
refresh_pattern -i \.rm$ 1440 50% 2880 ignore-reload
refresh_pattern -i \.swf$ 1440 50% 2880 ignore-reload
refresh_pattern -i \.mpeg$ 1440 50% 2880 ignore-reload
refresh_pattern -i \.wma$ 1440 50% 2880 ignore-reload
resource age =对象进入cache的时间-对象的last_modified
response age =当前时间-对象进入cache的时间
LM-factor=(response age)/(resource age)
举个例子,这里只考虑percent, 不考虑min 和max
例如:refresh_pattern 20%
假设源服务器上www.aaa.com/index.htm -----lastmodified 是 2007-04-10 02:00:00
squid上 proxy.aaa.com/index.htm index.htm进入cache的时间 2007-04-10 03:00:00
1)如果当前时间 2007-04-10 03:00:00
resource age =3点-2点=60分钟
response age =0分钟
index.htm还可以在cache停留的时间(resource age)*20%=12分钟
也就是说,index.htm进入cache后,可以停留12分钟,才被重新确认。
2)如果当前时间 2007-04-10 03:05:00
resource age =3点-2点=60分钟
response age =5分钟
index.htm还可以在cache停留的时间(resource age)*20%=12分钟-5=7
LM-factor=5/60=8.3%<20%
一直到2007-04-10 03:12:00 LM-factor=12/60=20% 之后,cache中的页面index.htm终于stale。
如果这时没有index.htm的请求,index.htm会一直在缓存中,如果有index.htm请求,squid收到该请求后,由于已经过期, squid会向源服务器发一个index.htm是否有改变的请求,源服务器收到后,如果index.htm没有更新,squid就不用更新缓存,直接把缓存的内容放回给客户端,同时,重置对象进入cache的时间为与源服务器确认的时间,比如2007-04-10 03:13:00,如果正好在这个后重新确认了页面。重置后,resource age变长,相应在cache中存活的时间也变长。
如果有改变则把最新的index.htm返回给squid,squid收到会更新缓存,然后把新的index.htm返回给客户端,同时根据新页面中的Last_Modified和取页面的时间,重新计算resource age,进一步计算出存活时间。
实际上,一个页面进入cache后,他的存活时间就确定了,即 (resource age) * 百分比,一直到被重新确认。
测试一个防盗链:
quid的缓存批量更新问题,因代理上有很多的域名,部分客户的网站如图片等会经常更新,要求又比较紧急,所以写了个自动清除缓存的脚本,后来网上也搜查了个,感觉还是别人的写的比较好,这里我把自己写的跟别人写的都记录下,方便以后查看。
我个人写的clear_squidcache.sh
- #!/bin/bash
- #clear_squidcache.sh
- FILE="/tmp/123.txt" #这里的123.txt中是存放更新文件的完整url路径。
- cat $FILE |while read line
- do
- /usr/local/squid/bin/squidclient -l 127.0.0.1 -p 80 -m PURGE $line >/dev/null 2>&1
- done
rm -f /tmp/123.txt
在网上找到高手写的:
- #!/bin/sh
- squidcache_path1="/data/cache1" # Squid 的缓存目录
- squidcache_path2="/data/cache2"
- squidclient_path="/usr/local/squid/bin/squidclient" # squidclient 的路径
- grep -a -r $1 $squidcache_path1/* | strings | grep "http:" | awk -F'http:' '{print "http:"$2;}' > /tmp/cache_list.txt
- grep -a -r $1 $squidcache_path2/* | strings | grep "http:" | awk -F'http:' '{print "http:"$2;}' >> /tmp/cache_list.txt
- cat cache_list.txt |while read url; do
- $squidclient_path -l 127.0.0.1 -m PURGE -p 80 $url # 80 端口根据你squid的http 设置自行修改
- done
rm -f /tmp/cache_list.txt
这个是我稍微修改过的,功能相对我个人写的要强大多了,可以拿来借鉴学习。用法也比较简单,保存脚本为clear_squid_cache.sh,赋予执行权限。
执行清除域名缓存:./clear_squid_cache.sh www.baidu.com
清除后缀缓存:./clear_squid_cache.sh jpg
清除特定文件缓存:./clear_squid_cache.sh 123.jpg
后续再研究研究,看看是否有更好的办法,或者再对脚本进行优化优化。
本文出自 “我的运维之路” 博客,请务必保留此出处http://newyue.blog.51cto.com/174760/629883
从我的独立博客中同步过来的,一起探讨
将近快一个月没写文章了,太懒散了,今天振作了一下,写了篇关于Squid的文章,Squid作为分布式代理缓存服务器真的非常的棒,希望本文对你有帮助。
版权声明:非商业自由转载,保留原文内容完整性,并署名作者王国峰和原文链接
前言
上一篇我表明了自己对缓存的立场:缓存一切可以缓存的资源。并讨论了如何利用IIS自身的缓存功能来轻松满足中小规模的图片缓存需求。关于IIS的客户端缓存和服务器端缓存的介绍大家可以回顾这篇文章。自从上一篇文章发表后,有不少朋友向我反馈:用IIS自身的缓存功能负载有限,建议使用Varnish或Squid。是的,我非常同意,所以我今天就和大家来探讨一下分布式代理缓存服务器Squid在图片存储架构中的应用,文中的一些观点,如有错误,敬请指出,谢谢。
Squid简介
Squid是一款高性能分布式代理缓存服务器,它一般用来做前置Web Cache,加快用户访问Web的速度。为了说明其运行过程,我将仍旧沿用我前一篇的YD风格,再一次请出人见人爱、花见花开、车见爆胎的空空老师,请读者自觉送出掌声:
Squid君是时下最受欢迎的空空作品代理人,为了让所有空空迷能更快捷地欣赏到高质量的空空作品,Squid君天天加班加点,整理和保存空空的最新作品,并对其作进一步的优化处理,比如去码。
有一天,我无聊至极,便打电话给Squid君,向他要最新的空空写真图(向Squid发出下载请求);
Squid君仔细辨别了一下我的声音,发现是老朋友,于是便答应了我的请求(Squid中的ACL访问控制,只接受合法的请求);
Squid君对我说他手头刚好有一周前的空空写真,问我看过没有,我说发过来看看呗,于是他很快发给了我(Squid缓存命中,下载极快,哦耶!);
我收到写真图,发现是两天前已经看过了的,于是告诉Squid君要最新的,Squid君看了看库存,发现手头没有最新的了,于是就说让我等一会儿,他去问问其他的代理兄弟有没有,我说好的,谢谢(Squid支持分布式集群方式,各个父子节点、兄弟节点之间的缓存数据可以互相同步);
结果空欢喜一场,他回来和我说其他兄弟也没有,当我非常失落的时候,他突然说空空今天来杭州,他可以直接向空空要写真,我一开心就对他说,快去快去(当Squid缓存不命中时,只能从源服务器获取数据);
过了好久,Squid君回来了,他说见空空的人实在太多了,排了好久的队才拿到她最新的写真图呢,我谢过之后他就把写真很快地发给了我。之后他说他一定要把这个写真保存起来,以便提供给其他空空迷和其他兄弟代理(Squid会把从源服务器获取的数据保存到自己的缓存中,如果下一个用户提出同样的下载请求,Squid直接把缓存中的数据给用户,当然也可以把数据奉送给其他兄弟代理,独乐乐不如众乐乐)。
到这里,我相信你已经大概明白Squid的工作过程了吧,下面我就对Squid特点做一下简要概括:
Squid官方网站:http://www.squid-cache.org/
你可以在官网上下载Squid以及阅读相关文档,当然接下来我也会用Chinese向大家介绍Squid的用法。
Squid配置详细说明
下面是一份详细的Squid的配置清单及其说明:
#http_port指令告诉squid在哪个端口侦听HTTP请求。默认端口是3128,除下面的形式外,也可以是http_port 192.168.63.50:3128
http_port 3128
icp_port 3130
#缓存目录的设置,可以设置多个缓存目录,语法为:<cache_dir> <aufs|ufs> <目录所在> <MBytes大小> <dir1> <dir2>
cache_dir ufs /var/spool/squid 1000 64 1024
#下面是关于日志文件的放置目录与文件名!
cache_access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log
cache_store_log /var/log/squid/store.log
pid_filename /var/run/squid.pid
#关闭认证机制,有些版本的 squid 会自动的加入代理认证机制,而普通情况下是不需要的,故找到包括auth_param的行,给它们加上注释
#auth_param basic children 5
#auth_param basic realm Squid proxy-caching web server
#auth_param basic credentialsttl 2 hours
#设置squid用户及用户组、管理员账号
cache_effective_user squid
cache_effective_group squid
cache_mgr [email protected]
# 与内存有关的配置:因为我的系统内存很小,所以只给 8 MB!如果您的物理内存很大的情况下,例如 512 MB,可以考虑加大到 64 或 128 MB。
cache_mem 128 MB
# 与磁盘容量有关的配置(注:下列的 90 与 95 是百分比 ),如果您的 cache_dir 所在磁盘很大时,可以考虑将 4096 改成 32768 KB
cache_swap_low 90
cache_swap_high 95
maximum_object_size 4096 KB
# 与内存保存资料有关的配置
maximum_object_size_in_memory 8 KB
#定义acl(访问控制列表), 语法为:acl<acl> <acl名称> <acl类型> <配置的内容>
#黑体为用户自定义部分
acl All src 0/0
acl Manager proto cache_object
acl Localhost src 127.0.0.1/32
acl Safe_ports port 80 21 443 563 70 210 280 488 591 777 1025-65535
acl SSL_ports 443 563
acl CONNECT method CONNECT
acl MyNetwork src 192.168.0.0/16
#利用前面定义的acl,定义访问控制规则
http_access allow Manager Localhost
http_access deny Manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow MyNetwork
http_access deny All
#定义与其它代理服务器的关系,语法: <cache_peer> <主机名称> <类别> <http_port> <icp_port> <其它参数>
cache_peer 192.168.60.6 parent 4480 7 no-query default
#设置与其它代理服务器的关系:
# <cache_peer_access> <上层 Proxy > <allow|deny> <acl名称>
#cache_peer_access 192.168.60.6 allow aclxxx
#cache_peer_access 192.168.60.6 deny !aclxxx
coredump_dir /var/spool/squid
注意:以上的配置说明来自这里。
配置好以后,我们就可以启动squid了,启动的步骤如下:
1). 我们可以运行下面的命令来检查配置文件的正确性:
# squid -k parse
只有这一步正确你才可以进行下一步的操作
2). 初始化cache目录.即建立缓存目录的存储格式
只需在第一次启动squid服务之前执行(在初次运行squid之前,或者无论何时你增加了新的cache_dir,你必须初始化cache目录。)
# squid -z
cache目录初始化可能花费一些时间,依赖于cache目录的大小和数量,以及磁盘驱动器的速度。假如你想观察这个过程,请使用-X选项:
# squid -zX
3). 启动squid服务
# service squid start
假定squid安装在/usr/local/squid目录下,也可以
# /usr/local/squid/sbin/squid -sD
最后,我推荐你去看看Squid权威指南,并希望你可以利用Squid成功搭建一个分布式图片缓存系统,Squid真的很棒!
为了你和你家人的健康,转载请注明原文出处:http://www.itivy.com/ivy/archive/2012/3/10/squid-usage.html
另外,我觉得你可能还会对下面架构相关的文章感兴趣:
优酷网架构学习笔记
百万级访问量网站的技术准备工作
Facebook图片存储架构的学习
facebook图片存储架构技术全解析
首先要明确一下,squid 能够用来作什么。很多人没有搞明白 squid 的工作原理,只是听说 squid 性能不错可以用来给网站提速,就直接在自己的 website 前面套了一个 squid ,这基本没有任何用处,即使你都是静态页面,后面apache上面没有开 mod_expires,一样缓存不了,squid只能起到一个连接管理的用处。
一般说来,网站用 squid 加速,目的有二种
1: squid 本身具有缓存功能,可以将webserver输出的内容缓存起来,在缓存没有过期之前来的访问,都直接用缓存里面的内容,这样可以有效减少 webserver 机器上面的请求数量。这是 squid 的主要功用。
2: 网络慢的用户会长时间占用 webserver 的 TCP 连接,webserver 对每个连接占用的资源比较大,如果长时间不能释放出来服务其他请求,性能会有比较大的影响。前面放一个 squid, webserver 就可以迅速处理完逻辑以后,把数据快速发送给 squid, 然后去处理别的逻辑,而 squid 每个 TCP 连接占用的资源很少,不用担心占用太多资源。这个用途也叫做连接管理,有一些网络设备也可以做这个事情,价格都很贵。
下面针对 squid 的两种功用,来讲述如何调整业务逻辑和 squid 参数
预操作
在搞 squid 之前,不管你用什么编译配置,需要什么特殊选项,都请 –enable-snmp ,并配置好 mrtg 之类,可以图形化的显示 squid 状态,例如 Request Hit Ratio(RHR), Byte Hit Ratio(BHR), 等等,反馈是做一切事情的基础,优化也不例外。
缓存
A: 使用 Expires header 来控制缓存
squid在缓存webserver内容的时候,需要后端webserver输出一些控制信息告诉他页面是不是可以被缓存,以及可以缓存多久。否则 squid 是不会自作主张给你缓存内容的。一个页面到底能不能缓存,只有开发网站的人才知道,因此开发人员有责任在动态页面里面输出 Expires 和 Cache-Control header。简单举一个 php 的例子以说明这两个 header 的值是什么含义,其中$expiretime 的单位是秒。
header(”Expires: ” . gmt_date_format(time()+$expiretime));
header(”Cache-Control: max-age=” . “$expiretime”);
对于静态文件,有两种方式来让 squid 自动给静态文件缓存,一种是使用 apache 的 mod_expires ,可以针对路径或者针对文件类型/扩展名来自动输出 cache 头。详细的请参考 mod_expires 的说明 。另一种是用 squid 的 refresh_pattern 来指定。详细的还是请参考 squid 的配置文件。一般来说,如果后端不是配置很麻烦,建议还是在后端做,前端的配置修改大多数都是违背http协议的,如果出现问题,也比较难排查。
B 根据 squid 访问的模式,进行业务拆分
进行了 Expires Header 的处理以后,squid 就真正可以起到加速的作用了,你可能也能感觉到,网站的访问速度明显加快。但是不要满足于这点成绩,查看 squid 的 snmp 统计图,通常 hit ratio 并不会太高,有 50% 就了不起了。这就是我们需要进一步优化的,我们的目标是让大部分 squid 都达到 9X% 的命中率。
为什么 squid 命中这么低呢,这大概有两种原因。大多数的网站都是有一些页面不能够被缓存的,例如登录页面。这些页面请求也从 squid 走,成为分母的一部分,直接就降低了命中率,我们首先可以做的事情是,把这些不能够缓存的页面请求,拆分到单独一个 squid 上面,或者访问量不大的话,干脆把 apache 暴露出来。这样能够缓存的那个 squid 命中率马上上升一截。
有人可能会说,把不能缓存的页面分拆开去,就光为了让能缓存的那个数字好看,这不是掩耳盗铃么?其实这么做是有意义的,首先就是去掉了不能缓存页面 的干 扰,使得我们进一步优化 squid 的依据更加准确。其次是不可缓存请求和可缓存请求之间的重要性通常是有差距的,分拆了以后,它们之间不容易互相抢占资源,不会因为下载图片的连接太多把 squid 占满,影响更重要的登录请求。第三就是可缓存内容通常是图片等页面元素, 浏览器在 load 它们的时候,对每个站点的并发连接会有控制,如果分开成不同的IP,可以多一些请求同时执行。提高少许显示速度。
其实观察 sohu, sina 之类的页面,你会发现它们的页面也是分拆的,可以看到页面里面的图片都是指向 images.sohu.com 之类的地址,虽然它们可能和其他页面一样后台都指向同一个 apache。
这样做完,缓存命中率大概能上升到 70%-80% 了,运气好的时候完全可以上 90%。
另一种导致 squid 命中低的原因和这个比较类似,同样都是可缓存的内容,有的可能是软件下载站上面的大文件,有的是新闻站点上面的小图片,如果同一个 squid 对这样差别巨大的文件加速的话,会严重干扰 squid 的缓存策略,两者不能兼顾,要不就是大文件占据了 cache ,把小文件都挤出了 cache, 要不就是小文件特别多,大文件无法进入 cache, 导致大文件经常 miss 。这个比不能缓存的页面还要恶心,因此即使在服务器资源有限的情况下,也要优先拆分这两类型访问。一般来说,文件大小分界线定在 1M 左右就可以了,如果是有软件下载这样特别大的文件,可以在 4M – 10M 左右再拆分一次。对于不同访问类型的 squid, 其系统优化参数也会有所不同,这个我们后面还会讲到。
只要悉心按照访问模式来拆分业务,大部分起缓存作用的 squid 都可以达到很高的命中率,至少都可以到达 9X%。
C 根据不同的需求,调整参数优化缓存
完成 A 和 B 两步优化以后, squid 的命中率经常可以达到 9x%, 可以说我们已经给 squid 创造了非常优秀的外部环境,下面我们就要从 squid 本身入手,通过调整它的缓存参数和缓存策略,甚至系统的参数,来让 squid 发挥出更好的性能。
在 B 步骤中,我们把 squid 划分成了三种用途,缓存大文件,缓存小文件,不缓存文件,这其中最后一种用途情况下面 squid 不起到缓存效果,只用来做连接管理,因此我们把它放到后面的连接管理里面叙述,这里只讨论和缓存相关的 squid 参数。
squid 有内存缓存和磁盘缓存两级缓存, 通常来说, 只要是专门给 squid 用的机器, 内存缓存都建议开得比较大, 大内存缓存总是有好处的嘛, 但是注意不要使得系统开始吃 swap ,像Linux这样一开始吃 swap 性能就下降比较严重的系统尤其要注意. 这个程度需要自己试验确定.
通常 1G 内存的Linux机器用来跑 squid ,内存缓存可以开到 512M.
有些libc比较差的平台, 例如比较老的 freebsd 系统, 其 malloc 函数的质量不高,可能会造成比较多的内存碎片,导致 squid 运行一段时间以后分配不出来内存挂掉. 这时候推荐在编译时候使用 dlmalloc package. 即使如此, 仍然要再缩小 squid 的内存缓存,以防不幸发生.
磁盘缓存的情况比较复杂, squid 有 ufs, aufs, coss, diskd, null 五种存储后端, 其中 ufs, aufs, diskd 都是在文件系统上面保存很多小文件, coss 是 squid 自己实现了一个简单的文件系统,可以使用一个大文件或者一个磁盘设备来存储. null 则是给不想要磁盘缓存的情况准备的. coss 看起来好像比较拽, 但是以前试验并不足够稳定,因此并不推荐使用. 剩下的三种存储方式,具体选择哪种需要根据操作系统的特性来进行.
ufs 是最传统的存储方式, 我们知道, squid 是一个单进程的程序, 它使用 ufs 存储后端时, 直接在进程里面读写文件. 这是一种很简单的方式, 缺点是当读写磁盘被阻塞的时候, squid 不能够处理请求, 会造成服务质量波动比较大. 因此出现了 aufs 和 diskd 两种存储后端, 原理都是 squid 主服务循环不负责读写文件, 而是通过消息队列或者tcp/pipe连接将数据传送给其他的线程(aufs)/进程(diskd), 然后其他线程/进程进行读写. 很显然,这两种存储方式有一定的通信开销, 因此不一定就比 ufs 好, 需要具体问题具体分析
前面说到, ufs/aufs/diskd都是在文件系统上面存储很多小文件,因此文件系统本身的特性严重影响了squid缓存的性能,对于 Linux ,强烈推荐用 reiserfs 等适合处理小文件的文件系统, bsd 则至少要打开 softupdate, 以及 dirhash 等一切对很多小文件有好处的选项. 在比较新的系统上面, reiserfs 等文件系统的性能已经足够优越, 通常 ufs 就已经可以应付需要. 对于一些老系统,使用 aufs 或者 diskd 是比较好的选择,如果系统的线程库比较好(如Linux,Solaris),那么使用 aufs, 否则 diskd.
也有一些例外情况, 比如多 cpu 的 Linux 2.6 系统, 线程库很优秀, 虽然 ufs 本身已经比较快了,但是 squid 单进程无法利用另外的 cpu , 不如使用 aufs , 让另外的 cpu 也可以起到一些作用, aufs 在编译的时候可以选择使用几个读写线程. 这个个人觉得稍微超过 cpu 个数就可以了.但是并没有实际测试过.
磁盘缓存开多大? 这个问题没有固定答案. 需要经过试验来确定, 一般来说开大一些没有太大问题. 只要你的硬盘足够