普及:
linux运维中,web cache server方案的部署是一个很重要的环节,选择也有很多种比如:varnish、squid、nginx。
下面就对当下常用的这几个web cache server做一对比:
1)从功能上说:varnish和squid是专业的cache服务,而nginx的cache功能是由第三方模块完成。
2)要做cache服务的话,肯定是要选择专业的cache服务,优先选择squid和varnish。
Varnish 可以认为是内存缓存,速度一流,但是内存缓存也限制了其容量,缓存页面和图片一般是挺好的;
varnish本身的技术上优势要高于squid,它采用了“Visual Page Cache”技术,在内存的利用上,Varnish比Squid具有优势,它避免了Squid频繁在内存、磁盘中交换文件,性能要比Squid高。
varnish是不能cache到本地硬盘上的。
Varnish可以使用正则表达式快速、批量地清除部分缓存
varnish的内存管理完全交给内核,当缓存内容超过内存阈值时,内核会自动将一部分缓存存入swap中让出内存。以挪威一家报社的经验,1台varnish可以抵6台squid的性能。
varnish用来做网站和小文件的缓存,相当给力的,做图片cache之类的合适
varnish没有专门的存储引擎
3)squid是功能最全面的比较传统的web cache server,有自己的存储引擎。,但是架构太老,性能不怎样。
squid可以用于缓存更多更大的内容,属于专业用语缓存的功能,比如尤其适合缓存图片、文档等;
squid可以说是越俎代庖自己实现了一套内存页/磁盘页的管理系统,但这个虚拟内存swap其实linux内核已经可以做得很好,squid的多此一举反而影响了性能
squid支持正向代理缓存,而这方面varnish、nginx cache做不到
4)nginx本来是反向代理/web服务器,用了插件可以做做这个副业,但是本身不支持的性能比较多。
nginx是用第三方模块ncache做的缓冲,其性能基本达到varnish,但在架构中nginx一般作为反向(静态文件现在用nginx的很多,并发能支持到2万+)。
在静态架构中,如果前端直接面对的是CDN活着前端了4层负载的话,完全用nginx的cache就够了。
nginx
Cache是为了提供访问最频繁资源的缓存而已,适合缓存纯文本体积较小的内容,缓存少量页面资源,主业是提供Web服务与代理的作用,若是Cache内容过多容易造成性能瓶颈与负载过大.
nginx也没有专门的存储引擎,nginx可以认为是已个七层LB,再加上可以嵌入各种脚本语言,实现WAF规则和七层的定制开发策略非常容器,但要是作为专门的web cache server还要差不少。
针对CDN方案的实现:如何选择squid、Varnish、Nginx+memcache?
CDN的全称是Content Delivery Network,即内容分发网络。
其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。
1.使用CDN有3个好处
1)优化跨ISP网络访问速度,在国内大联通和大电信之间是世界上最远的距离,在国外,中国和其他地区很平行,用cdn可以优化全球响应速度
2)节约流量成本,CDN机房都一般都放在带宽便宜的小城市,带宽成本大概是BGP机房的1/3
3)快速提升性能,对于结构复杂的系统,部署CDN可以在不改动代码段情况提升网站整体性能,立竿见影
2.市面上有很多CDN供应商,比较著名有:
Akamai (全球最大)
webluker
cloudflare
chinacache(蓝汛)
网宿CDN
帝联CDN
阿里CDN(web cache server 叫swift)
腾讯CDN
七牛云融合CDN
3.如果需要自己搭建CDN系统,有3种主流方案可以选择:squid、varnish、Nginx+memcache.
1)对于大规模网站的CDN,存储共享是个强需求。为了消除单点,不可能只使用一台CDN服务器,如果只是简单做负载均衡,单台CDN server上需要存储全部数据,存储利用率太低了。
squid支持几个实例并联,实际使用的人不多;
varnish 只能用单实例;
nginx+memcache 天然的分布式存储;
当然,采用squid/varnish 也有解决办法: 需要在它们前面部署一个支持url hash的负载均衡设备(硬件,软件均可,比如说haproxy)
2)内存存储的代价
如果CDN把缓存放在内存当中,固然性能会有提升,但是当服务遭遇故障重启之后,全部数据都会丢失需要重建,这个时候会给后端应用服务器带来很大的短时压力服务需要较长的时间才能完全恢复.
而实际运行当中,由于各种原因,CDN服务重启的概率相当高.
3)一个很悲剧的事实
对动态网页使用CDN,无论squid还是varnish都不能直接用,都需定制代码。
例如varnish会判断response的header,如果发现里面有set-cookie项,它就认为这个页面不应该被缓存。对于规模庞大/OOP封装严密的网站,普通程序员根本意识不到调用哪一个fucntion会输出set-cookie,这个会导致CDN命中率急剧降低。但你也无力去对每行代码做code review,没有办法,只能去修改varnish代码了,这又引入一个新的维护成本. Squid也有这个问题
4)purge效率
purge就是CDN删除缓存项的接口,国内的UGC网站,因为严厉的内容检查制度和泛滥的垃圾广告,删帖子删图片特别频繁,某些网站可能高达40%(发100个贴,有40个帖子可能被删除或者修改),所以对purge的效率有要求。
squid和varnish的purge效率都达不到国内这种强度要求,nginx+memcache purge性能要好很多。
在当前的中国,遇到突发事件后,要是不及时删除指定的链接或内容,后果可能会很严重(小到个人被炒,大到公司被关都有可能)
5)推荐CDN方案
中小型网站直接买CDN服务就好,现在CDN已经进行按需付费的云计算模式了,性价比是可以准确计算的;
外地部署单点,推荐用squid;
在公司内部实施私有云战略,推荐nginx+memcache; 不太建议使用varnish。
之前cdn方面接触过squid,但是与varnish相比,其还有很多缺点,现基本不再应用squid,所以我们本次实验用的是varnish
Varnish与Squid的对比 Squid是一个高性能的代理缓存服务器,它和varnish之间有诸多的异同点。
相同点: 1. 都是一个反向代理服务器。 2. 都是开源软件。
不同点:如下
Varnish的优点:
Varnish的稳定性很高,两者在完成相同负荷的工作时,Squid服务器发生故障的几率要高于Varnish,因为使用Squid要经常重启。
Varnish访问速度更快,所有缓存数据都直接从内存读取,而squid是从硬盘读取
Varnish可以支持更多的并发连接,因为Varnish的TCP连接释放要比Squid快。因而在高并发连接情况下可以支持更多TCP连接。
Varnish可以通过管理端口,使用正则表达式批量的清除部分缓存,而Squid是做不到的。
Varnish
高性能、开源的反向代理服务器和内存缓存服务器。
优点:
1. 高性能;
2. 多核支持;
3. 支持0-60秒的精确缓存时间。
缺点:
1. 不具备自动容错和恢复功能,重启后数据丢失;
2. 在线扩容比较难。
3. 32位机器上缓存文件大小为最大2GB;
4. 不支持集群。
应用场景:并发要求不是很大的小型系统和应用。
◆Squid
很古老的反向代理软件,拥有传统代理、身份验证、流量管理等高级功能,但是配置太复杂。它算是目前互联网应用得最多的反向缓存代理服务器,工作于各大古老的cdn上。
优点:
1.完整的庞大的cache技术资料。
2.很多的应用生产环境
◆Nginx
1.不支持带参数的动态链接。
2.Nginx缓存内部没有缓存过期和清理的任何机制,这些缓存的文件会永久性地保存在机器上,如果要缓存的东西非常多,那就会撑暴整个硬盘空间。
3.只能缓存200状态码,因此后端返回301/302/404等状态码都不会缓存,假如恰好有一个访问量很大的伪静态链接被删除,那就会不停穿透导致后端承载不小压力
4.Nginx不会自动选择内存或硬盘作为存储介质,一切由配置决定,当然在当前的操作系统里都会有操作系统级的文件缓存机制,所以存在硬盘上也不需要过分担心大并发读取造成的io性能问题。
◆总结:
缓存加速(静态加速、节省带宽、边缘推送):Varnish > Squid >Nginx
反向代理(路由加速、隐藏主节点):Nginx > Varnish > Squid
Varnish
使用缓存有两个前提条件,一是数据访问热点不均衡,某些数据会被更频繁的访问,这些数据应该放在缓存中;二是数据在某个时间段有效,不会很快过期,否则缓存的数据就会因已经失效而产生脏读,影响结果的正确性
网站应用中,缓存除了可以加快数据访问速度,还可以减轻松后端应用和数据存储的负载压力,这一点对网站数据库架构至关重要,网站数据库库几乎都是按照有缓存的前提进行负载能力设计的
Varnish is a reverse HTTP proxy, sometimes referred to as a HTTP accelerator or a web accelerator.
2. Varnish stores files or fragments of files in memory, allowing them to be served quickly.
3. Varnish is essentially a key/value store, that usually uses the URL as a key.
4. Varnish is designed for modern hardware, modern operating systems and modern work loads.
Varnish是一个反向HTTP代理,有时称为HTTP加速器或web加速器。
2. Varnish将文件或文件片段存储在内存中,使它们能够快速被提供。
3.Varnish本质上是一个键/值存储,它通常使用URL作为键。
4. 清漆是为现代硬件、现代操作系统和现代工作负载而设计的
#Web Cache
程序具有局部性:
时间局部性
空间局部性
key-value:
key:访问路径,URL,hash
value:web content
缓存对象:
热点数据
命中率:(hit/(hit + miss))
文档名中率,从文档个数进行衡量
字节命中率,从内容大小进行衡量
注意:
缓存对象:生命周期,定期清理
缓存空间耗尽,LRU(最近最少原则)
可缓存,不可缓存(用户私有数据)
什么是CDN
CDN:缓存网络,Content Delivery Network,即内容分发网络;加速器,反向代理缓存
基本原理:广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或
网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求
内容管理和全局的网络流量管理(Traffic Management)是CDN的核心所在。通过用户就近性>和服务器负载的判断,CDN确保内容以一种极为高效的方式为用户的请求提供服务
总的来说,内容服务基于缓存服务器,也称作代理缓存(Surrogate),它位于网络的边缘,距用户仅有"一跳"(Single Hop)之遥。同时,代理缓存是内容提供商源服务器(通常位于CDN服务提供商的数据中心)的一个透明镜像。这样的架构使得CDN服务提供商能够代表他们客户,即内容供应商,向最终用户提供尽可能好的体验,而这些用户是不能容忍请求响应时间 有任何延迟的
####VCL的处理流程
vcl compiler:配置接口
vcl compiler通过调用外部的C cpmpiler(C编译器)进行编译,这就要依赖gcc编译器,然后生成一个二进制格式的配置对象,这个二进制格式的配置对象可以被各Child和cache子进程所加载读取相关配置
所以,每一次修改varnish配置文件,都要手动加载、编译、装载、使用;支持动态装载
vcl 的处理流程,主要是由 Varnish 的状态机决定,可以通过 vcl 配置文件来对 varnish 状态机各个步骤所做的操作进行配置
vcl_recv
vcl_recv 是 http 请求到达后进入的第一个状态,在这个状态中,可以对请求进行以下的一些处理
1. 修改 client 请求,以减少缓存决策时的差异性。
2. 根据 client 请求,决定缓存策略。
3. 重定向请求
4. 决定处理请求的 backend(即后端 webserver )
vcl_deliver
在缓存数据将要发送到客户端时调用
什么是 sysctl
sysctl命令用于运行时配
-a 显示所有的系统参数置内核参数 ##增大内存到2048 就能达到varnish进程的需要
什么是 ulimit
ulimit是指每个user使用各种资源的限制值。ulimit 命令用来限制系统用户对shell资源的访问,它是一种简单并且有效的实现资源限制的方式
ulimit -a
ulimit -n 131072
####################################################
MEMLOCK=82000 ##内存锁定(就是运行varnish需要82M内存空间,但是系统只允许64M,所以也要修改)
ulimit -l 82
#####################################################
net.core.optmem_max = 20480 #每个套接字所允许的最大缓冲区的大小
net.core.rmem_default = 212992 #网络协议栈默认接收内存
net.core.rmem_max = 212992 #网络协议栈最大接收内存
一.部署单个后端服务器的varnish
第一步:首先ssh连接(次实验需要2个虚拟机和真机)
将server1当做varnish服务器,将安装包从真机传入server1
第二步:在server1安装varnish软件包
vim /etc/logrotate.d/varnish是基本的环境变量
vim /etc/varnish/varnish.params是服务的基本配置文件(稍后将端口改为80)
varnish服务的说明文档
vim /usr/lib/systemd/system/varnish.service是varnish服务启动脚本
里面有一些最基本的参数:允许开启的文件个数 内存锁定大小
ulimit -l查看系统的内存大小
free -m查看系统的剩余内存
sysctl -a | grep file查看系统允许开启文件的最大个数
MEMLOCK=82000 ##内存锁定(就是运行varnish需要82M内存空间,但是系统只允许64M,所以也要修改)
ulimit -l 82
第三步:查案打开文件数,发现我们打开的文件数与varnish说明的打开文件个数上限不匹配
第五步: vim /etc/security/limits.conf系统参数限制文件
查看系统允许的内存锁定和文件连接最大,发现系统只允许64M内存锁定,需要去修改注意:因为varnish这个程序运行在varnish这个用户的私有空间内,内核对普通文件限制的最大文件数为98846,对varnish用户限制的最大文件数为131072,所以我们需要满足这个最大值
第六步:在配置文件中进行那个配置,使其可以作为server2的反向代理
server1上面设置,将server1作为一个代理服务器,它的后端服务器是server2这个web服务器
配置单个后端服务器
第七步:修改varnish端口,将其修改为80
手动清除缓存
varnishadm ban req.url "~" / #清除所有
varnishadm ban req.url "~" /index.html #清除index.html页面缓存
curl -I 172.25.0.1/index.html 和curl -I 172.25.0.1 这两个命令所构建的http请求报文是不一样的
查看缓存命中情况
vim /etc/varnish/defaults.cvl
写入sub vcl_deliver模块 (evince varnish.pdf 打开pdf文档进行复制 )
evince 可以打开pdf文件进行复制
写入两种情况:server1有缓存,server1没有缓存
systemctl restart varnish
缓存是否命中:会发现没有缓存时是X-Cache: MISS from westos cache,访问过一次缓存保存后,再次访问时会显示击中X-Cache: HIT from westos cache,说明缓存命中。
deliver:缓存取到的对象,并发送至服务端
vcl_deliverpa
在缓存数据将要发送到客户端时调用
vim /etc/varnish/default.vcl
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT from westos cache";
}
else {
set resp.http.X-Cache = "MISS from westos cache";
}
return (deliver);
}
systemctl restart varnish
第一次去代理服务器上要,代理服务器上没有缓存,需要到后端服务器上,第二次就有了直接从缓存中读取。
url "~" / 清除目录缓存
url "~" /index.html 清除网页缓存
二.搭建一个具有多台后端服务器的varnish系统(内含负载均衡)
server1代理服务器要同时为多台服务器缓存数据,server1同时为多个web服务器做代理
注意这个时候varinish作为代理每次让客户端去访问后端的web服务器,和上面的并没有把数据缓存在自己的身上,因此不要混淆(参考return (pass)的使用)
实际上企业当中的web后端服务器(为客户端提供资源的服务器)的性能有好有坏
性能差一点的就让它少干一点活,性能好的就多分担一点
现在就是server2这个web服务器性能比较差,server3这个服务器性能比较好
客户端通过varnish加速器访问server2的时候去轮询server3
实际上server2和server3上面存放的资源一模一样,只是为了实验效果明显起见,写为www.westos.org和bbs.westos.org
当客户端第一次访问server2的时候varnish去问server2要资源
当客户端第二次访问server2的时候varnish去问server3要资源
这个时候server2和server3上面的资源一模一样,客户端根本察觉不到,也缓解了server2(性能差)的访问压力
客户端通过varnish加速器访问node3的时候只去找node3(性能好)
以上这个思想就是在node2和node3之间实现调度(负载均衡),这个调度就是在varnish这个加速器上面实现的
实现负载均衡的调度算法很多,为了实验效果明显起见,我们使用轮询方式的均衡(就是轮着干)
###定义不同域名站点的后端服务器
再启一台虚拟机,安装httpd , 写index.html --> bbs.westos.org
在物理机上写好本地解析
vim /etc/varnish/default.vcl
backend web1 {
.host = "172.25.0.2";
.port = "80";
}
backend web2 {
.host = "172.25.0.3";
.port = "80";
}
sub vcl_recv {
if (req.http.host ~ "^(www.)?westos.org") {
set req.http.host = "www.westos.org";
set req.backend_hint = web1;
} elsif (req.http.host ~ "^bbs.westos.org") {
set req.backend_hint = web2;
} else {
return (synth(405));
}
}
systemctl restart varnish
再访问时,不同域名对应不同主机
配置server3也就是web2
实现了最基本的具有两台后端,但是两台后端之间没有任何关系
定义负载均衡
#vcl4.0以后定义负载均衡需要导入模块!!!!
man vmod_directors
vim /etc/varnish/default.vcl
'在配置文件前面加上下面内容'
##一定要加在正确的位置 不能加在文件的最开头
import directors from "/usr/lib64/varnish/vmods/libvmod_directors.so";
# Default backend definition. Set this to point to your content server.
sub vcl_init { ##定义负载均衡
new lb = directors.round_robin();
lb.add_backend(web1);
lb.add_backend(web2);
}
sub vcl_recv {
if (req.http.host ~ "^(www.)?westos.org") {
set req.http.host = "www.westos.org";
set req.backend_hint = lb.backend(); ##当访问www.westos.org时,请求转到lb
#return (pass); ##测试时可打开此选项,不进行缓存,(时刻清除缓存,这是为了实验效果,在企业中是不需要的)
} elsif (req.http.host ~ "^bbs.westos.org") {
set req.backend_hint = web2;
} else {
return (synth(405));
}
}
systemctl restart varnish
测试(手动清缓存,或者加上不缓存的配置)
配置varnish文件
return (pass)就是不让varnish加速器缓存web服务器的资源,每次客户端一旦请求,varnish加速器就都去问web服务器要资源,如果缓存资源就看不到负载均衡的效果了。
现在其实web1上面的资源和web2上面的资源一样
当客户通过server1代理去找server2和server3的时候
应该实现调度,负载均衡,在server1上面实现负载均衡
使找server2的资源的时候负载均衡(这里使用轮询方式),性能不好的服务器
使找server3的资源的时候不负载均衡,因为他的性能比较好
三.配置varnish虚拟主机
实际在企业当中,比如百度的服务器:包括地图资源、新闻资源等等
现在我也想实现一台主机上放多个资源,也就是给web服务器建立虚拟主机,然后结合varnish加速器。
接下来我将在server3上面搭建apache虚拟主机(也就是可以在server3上访问到不同的资源,结合上面的,如果访问www需求大使得在server2,server3之间轮询,但是问题就是轮询了但是访问到的资源并不相同,一个是www.westos.org一个是bbs.westos.org 因此本次实验就是解决如果访问www的时候在server2和server3上访问的都是www,但是访问bbs的时候只是单纯的去访问server3上的资源bbs,因此提出了varnish虚拟主机 )
之前server2和server3都是仅有一个站点资源的web服务器
这篇文章是基于上一篇的负载均衡做的,才可以看到明显的实验效果
在server3上配置apache虚拟主机
##因为当前server3上以www.westos.org访问和bbs.westos.org访问看到的是同一个资源,都是bbs.westos.org:server3
(就是真机在访问www域名会轮询到web3,访问bbs域名访问的也是访问web3,所看到的资源是一样的 注意:web2和server3指的是同一台虚拟机)
在server3这台web服务器上面搭建虚拟主机
cd /etc/httpd/conf.d切换到编写虚拟主机配置文件的目录下
ls查看一下
vim vhost.conf编写虚拟配置文件
<VirtualHost *:80>
DocumentRoot /www
ServerName www.westos.org 虚拟站点一
</VirtualHost>
<Directory "/www">
Require all granted
</Directory>
<VirtualHost *:80>
DocumentRoot /bbs
ServerName bbs.westos.org 虚拟站点二
</VirtualHost>
<Directory "/bbs">
Require all granted 要求全部批准
</Directory>
#手动建立两个目录,并写好index.html
重启httpd,手动测试访问
注意:有些人可能会疑惑这里的www.westos.org跟之前的www.westos.org的关系,准确来说,配置的虚拟主机这个才是真的这个域名的拥有者,而我们前面认为的只是varnish将其当作web1,指定其为www.westos.org,所以,当真的域名主机出现后,会“顶替”掉之前的。
四.配置推送平台
什么是CDN推送
当后端服务器中的内容有更新的时候,在varnish的缓存中应该及时地同步后端服务器中的内容。相当于清空varnish中的缓存,当下一次进行访问时,直接从服务器中获取新的内容
CDN推送平台管理:简单的说就是利用web界面批量清除缓存
因为CDN管理需要apache服务,,所以要安装http服务,推送平台是用php语言写的,所以也需要server1支持php语言。
#在server1上:
yum install -y unzip php httpd ##修改httpd端口为8080并启动(varnish已经占用80)
unzip bansys.zip -d /var/www/html
mv /var/www/html/bansys/* /var/www/html
vim config.php
<?php
//varnish主机列表
//可定义多个主机列表
$var_group1 = array(
'host' => array('172.25.0.1'), varnish主机的信息
'port' => '8080',
);
//varnish群组定义 群组的目的是为了同时对多个varnish服务器进行缓存清理
//对主机列表进行绑定
$VAR_CLUSTER = array(
'www.westos.org' => $var_group1,
);
//varnish版本
//2.x和3.x推送命令不一样
$VAR_VERSION = "3";
?>
vim /etc/httpd/conf/httpd.conf
Listen 8080
访问: 172.25.0.1:8080
##有telnet和http两种,选择http,再添加varnish配置
首先在server1安装推送平台所需的软件包
将推送平台压缩包bansys.zip解压到共享目录下
编辑文件
修改httpd的端口
此时在页面可以打开这个推送平台页面,但是无法推送,因为没有配置推送
编辑代理服务器的权限列表(因为不是任何人都可以清除缓存)
vim /etc/varnish/default.vcl设置访问控制,即白名单
acl westos {
"127.0.0.1";
"172.25.0.0"/24; #指定0网段的可以推送,这个网段的所有主机都有权限清理代理服务器上面的缓存
}
}
if (req.method == "BAN") {
if (!client.ip ~ westos) {
return(synth(405,"Purging not allowed for " + client.ip)); ##如果不是允许的ip就拒绝清理
}
ban("req.url ~ " + req.url); ##如果是允许的ip就进行清理
return(purge);
}
systemctl restart varnish
网页:
访问: 172.25.0.1:8080
选择http
.* ##推送所有页面
/index.html ##推送index.html页面
如果不注释return(pass),不注销返回值一直是Miss,,不会出现hit
注释:return(pass),这个会一直清除缓存,之前的实验做的
清除这个代理服务器就不会缓存资源了,直接从服务器请求资源给客户端
输入.*,发送(清除所有缓存)