一、varnish系统的基本定义及概念
1.什么是varnish?
Varnish是一款高性能的 开源web加速器,任务是 反向代理并缓存他后面的web服务器的内容,并且响应用户的请求 。 varnish加速器(代理缓存服务器)是将从服务器要回来的资源放在自己的 内存 里,客户读取的速率很快,代理的效率高。
- Varnish本质上是一个 键/值 存储,它通常使用URL作为键。
- varnish是工作在用户层(应用层–>HTTP协议所在的层)
- varnish代理服务器的 两种工作方式:
(1)仅作为 代理服务器:帮客户端去问服务端要数据,要回来的数据直接给客户端自己不缓存一份,这种情况是客户的隐私信息、热点信息、更新比较快的数据,不缓存,只代理。
(2)既代理又缓存:帮客户端去问服务端要数据,要回来的数据先给自己缓存一份,然后再发给客户端,这种情况是用于更新比较慢的数据,此时varnish既代理又缓存。 - varnish讲解
- varnish安装的问题等
2、varnish与squid的异同点
-
squid加速器(代理缓存服务器) :将从服务器要回来的资源放在自己的 硬盘 里,客户读取的速率很慢,代理的效率低。
-
squid 与 varnish的相同点:
(1)都是一个反向代理服务器 (2)都是开源软件。
-
squid 与 varnish的不同点(Varnish的优点):
(1)Varnish的稳定性很高,两者在完成相同负荷的工作时,Squid服务器发生故障的机率要高于Varnish,因为使用Squid要经常重启。 (2)Varnish访问速度更快,Varnish采用了“Visual Page Cache”技术,所有缓存数据都直接从内存读取,而squid是从硬盘读取 , 因而Varnish在访问速度方面会更快。 (3)Varnish可以支持更多的并发连接,因为Varnish的TCP连接释放要比Squid快 ,因而在高并发连接情况下可以支持更多TCP连接。 (4)Varnish可以通过管理端口,使用正则表达式批量的清除部分缓存,而Squid是做不到的。
-
Varnish 缺点:
(1)varnish在高并发状态下CPU、IO、内存等资源开销都高于Squid。
(2)varnish进程一旦Hang、Crash或者重启,缓存数据都会从内存中完全释放,此时所有请求都会发送到后端服务器,在高并发情况下,会给后端服务器造成很大压力。
针对缺点二的解决方案 :在访问量很大的情况下推荐使用varnish的内存缓存方式启动,而且后面需要跟多台squid/nginx服务器。主要为了防止前面的varnish服务、服务器被重启的情况下,大量请求穿透varnish,这样squid/nginx可以就担当第二层CACHE,而且也弥补了varnish缓存在内存中重启都会释放的问题;
3.为什么要有varnish加速缓存代理服务器
实例:我们国家使用微信的用户非常多,微信的服务商腾讯总部在深圳,当每个地区的用户使用微信访问腾讯服务器的资源的时候,访问量太大,对于深圳的服务器来说,会造成很大的访问压力,甚至会造成服务器瘫痪,对于每个地区的用户来数,如果都去访问腾讯的总部服务器,会造成网络拥塞,使得客户的访问很缓慢,不利于用户的使用,现在腾讯总部给每个地区都放varnish代理服务器,每个地区的微信使用用户想访问深圳资源的时候,都会间接去问自己地区的varnish代理服务器要资源。如果varnish代理服务器上面没有资源,此时varnish代理服务器就会去向深圳的服务器要资源,将要回来的资源视情况而定给自己缓存一份,然后再给客户端发一份。这种情况下,varnish代理服务器的数量远远少于微信用户的数量,即使所有的varnish代理服务器同时向深圳总部的服务器要资源的时候,也不会给深圳的服务器造成很大的压力,对微信使用的客户端和深圳总部的服务端都有好处,假如代理服务器缓存了一些更新慢的数据,当客户端再次要这个数据的时候,代理服务器会直接返回给客户端,不需要再去问深圳的服务器要资源,那么这就是把varnish服务器叫做加速器的原因,加快了客户端和服务端之间的访问速率。
- 使用varnish作为web代理缓存的原理 : varnish是一个http反向代理的缓存。它从客户端接收请求然后尝试从缓存中获取数据来响应客户端的请求,如果varnish不能从缓存中获得数据来响应客户端,它将转发请求到后端(backend servers),获取响应同时存储,最后交付给客户端。 如果varnish已经缓存了某个响应,它比你传统的后端服务器的响应要快很多,所以你需要尽可能是更多的请求直接从varnish的缓存中获取响应。 varnish决定是缓存内容或者是从后端服务器获取响应。 后端服务器能通过http响应头中的Cache-Control来同步varnish缓存内容。在某些条件下varnish将不缓存内容,最常见的是使用cookie。当一个被标记有cookie的客户端web请求,varnish默认是不缓存。 这些众多的varnish功能特点都是可以通过写vcl来改变的。
4.varnish加速器的工作流程
- Varnish与一般服务器软件类似,分为master(management)进程和child(worker,主要做cache的工作)进程。varnish启动会产生两个进程,root身份产生manger主(管理mangerment)进程,然后fork一个worker子进程(varnish身份)
- master进程作用:读入命令,进行一些初始化,然后fork并 监控child进程 。读入(更新)配置,vcl 文件编译,varnish监控,初始化 varnish 及提供 varnish 管理接口。 Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。
- child进程作用: 主要接受请求,进行请求任务的处理,分配线程进行cache工作
- 作用机理 :
(1)child进程主线程初始化过程中,将存储的大文件整个加载到内存中,如果该文件超出系统的虚拟内存,则会减少原来配置mmap(mmap:memory mapper 内存映射)大小,然后继续加载,这时候创建并初始化空闲存储结构体,放在存储管理的struct中,等待分配。
(2)接着varnish某个负责接受新http连接的accept线程开始等待用户,如果有新的http连接,但是这个线程只负责接收,然后唤醒等待线程池中的work线程,进行请求处理。
(3)worker线程读入uri后,将会查找(从缓存中查找还是直接从后台fetch取决于VCL设置)已有的object(缓存中lookup此对象),命中(hit)直接返回,没有命中(miss)则会从后端服务器中(backend)取(fetch)出来,放到缓存中。如果缓存已满(expire),会根据LRU算法,释放旧的object。对于释放缓存,有一个超时线程会检测缓存中所有object的生命周期,如果缓存过期(ttl),则删除、释放相应的存储内存。 - 分配缓存的过程 :它根据所读到object的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个object的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上。如果缓存已满,就根据LRU机制,把最旧的object释放掉。释放缓存的过程是这样的:有一个超时线程,检测缓存中所有object的生存期
如果超初设定的TTL(Time To Live)没有被访问,就删除之,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前面或后面的空闲内存块。如果前面或后面的空闲内存和该释放内存是连续的,就将它们合并成更大一块内存。整个文件缓存的管理,没有考虑文件与内存的关系,实际上是将所有的object都考虑是在内存中。如果系统内存不足,系统会自动将其换到swap空间,而不需要varnish程序去控制。
5.什么是CDN?
- CDN:缓存网络,Content Delivery Network,即内容分发网络;加速器,反向代理缓存
- CDN加速实现:varnish
- 基本原理:广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。内容管理和全局的网络流量管理(Traffic Management)是CDN的核心所在。通过用户就近性和服务器负载的判断,CDN确保内容以一种极为高效的方式为用户的请求提供服务。总的来说,内容服务基于缓存服务器,也称作代理缓存(Surrogate),它位于网络的边缘,距用户仅有"一跳"(Single Hop)之遥。同时,代理缓存是内容提供商源服务器(通常位于CDN服务提供商的数据中心)的一个透明镜像。这样的架构使得 CDN服务提供商能够代表他们客户,即内容供应商,向最终用户提供尽可能好的体验,而这些用户是不能容忍请求响应时间有任何延迟的。
- 理解角度:从CDN的中文表义去理解:内容、分发、网络!
(1)内容
指储存在CDN节点上的动静态资源的分发和访问的数据内容,比如JS、CSS、图片和静态页面等静态资源!
客户端:用户一般从主站获取动态内容后,再从CDN下载相应的静态数据
(2)分发
就是如何让上面提到的数据内容(资源),快速的部署在这个网络中,从而快速为用户服务。
目的:通过调度让用户访问最近的资源!
(3)网络
1)是部署于者全球(国)的一大堆服务器--->集群
2)这些服务器基于当前互联网的基础架构在其上层再构成一个网络,这个网络专为资源分发而
6、CDN系统的理解
源站:指发布内容的原始站点。
操作:添加、删除、更改网站的文件,都是在源站上进行的;
明确:缓存服务器所抓取的对象也全部来自于源站
折叠:隐藏的含义,客户端并不知道折叠网站的存在,以为访问的资源站点就是源站!
缓存服务器:是直接提供给用户访问的站点资源(直接面对用户),由一台或数台服务器组成;
2)用户请求资源的过程
1)当用户发起url请求时,他的访问请求被智能DNS定位到离他较近的缓存服务器;
2)如果用户所请求的内容刚好在缓存里面,则直接把内容返还给用户;
3)如果访问所需的内容没有被缓存,则缓存服务器向邻近的缓存服务器或直接向源站直接抓取内容,然后再返还给用户。
3)智能DNS
CDN整个技术核心是智能DNS,它主要根据用户的来源,将其访问请求指向离用户比较近的缓存服务器!
举例1:把深圳电信的用户请求指向到深圳电信IDC机房中的缓存服务器。
举例2:通过智能DNS解析,让用户访问同服务商下的服务器,消除国内南北网络互相访问慢的问题,达到加速作用。
二、搭建最基本的varnish系统
2.1 封装7.3的虚拟机(7.3母盘)
1、安装一个7.3的虚拟机
2、更改主机名:hostnamectl set-hostname server1
3、配置网络:
此时,systemctl restart network 重启网络会发现服务起不来。
解决此问题:
在配置文件 /boot/grub2/grub.conf 的第99行添加 net.ifnames=0 ,这样以后做的快照也都会是eth0.
4、关闭并禁用网络服务,会影响网络配置和DNS
systemctl stop NetworkManager
systemctl disable NetworkManager
reboot后,网络通了。
5、配置yum源:
利用真机172.25.70.250的共享yum源
在虚拟机中:在路径/etc/yum.repos.d/x下写一个yum源指向
检查yum源是否配置成功: yum clean all yum repolist
6、yum install vim net-tools lftp
7、关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
8、关闭selinux: vim /etc/sysconfig/selinux,修改完后需要reboot
9、添加解析: /etc/hosts/
10、关闭虚拟机并 在真机清理临时及缓存文件 :virt-sysprep -d rhel7.3
- 注意:如果在virt-manager中删除了母盘,则不能使用此命令。-d后加的是母盘名字。每次开机都会生成一些临时文件,若不清除,每快照都会有这些东西,快照会变大。
2.2 搭建最基本的varnish系统
1、利用母盘rhel7.3.qcow2创建三个快照:ran1,ran2,ran3,用来做后续的实验
qemu-img create -f qcow2 -b rhel7.3.qcow2 ran1/ran2/ran3
2、给快照导入镜像,登录3个快照,改名字server1 server2 server3,改ip 172.25.70.1 / 172.25.70.2 / 172.25.70.3 ,这次的yum源直接就能用,然后用真机连接快照server1 server2 server3。
在server1上,varnish缓存服务器
3、在 server1上搭建varnish代理服务器:登录真机172.25.70.250,安装三个varnish安装包。
yum install -y varnish-4.0.5-1.el7.x86_64.rpm varnish-libs-4.0.5-1.el7.x86_64.rpm jemalloc-3.6.0-1.el7.x86_64.rpm -y
4、
rpm -qc varnish 查看varnish服务的配置文件
rpm -qa | grep varnish 查看varnish版本
/etc/varnish/default.vcl #varnish核心配置文件
/etc/varnish/varnish.params #varnish的参数配置文件
5、vim /usr/lib/systemd/system/varnish.service 是varnish服务启动脚本,里面有一些最基本的参数:varnish的内存大小和缓存的文件数目
- 由于Linux是多用户和多任务的系统,所以默认对每个用户分配的资源是固定的;而varnish的运行也是以varnish的用户身份来运行,所以也会受到系统的限制。
6、vim /etc/varnish/varnish.params /etc/varnish/varnish.params是服务的基本配置文件,将端口改为80
7、 ulimit -a 查看系统的各种参数
8、(永久生效)vim /etc/security/limits.conf 系统参数限制文件,写入
varnish - nofile 131072
varlish - memlock 82000
- 由于值针对varnish用户,不希望针对所有的用户,所以在配置文件中对varnish用户进行配置!
9、(临时生效、全局)
ulimit -n 131072 修改文件描述符
ulimit -l 82 修改内存
10、 vim /etc/varnish/default.vcl 设置后端服务器 是ip为172.25.70.2这个web服务器
11、开启server1,varnish代理缓存服务器
12、 在server2上,web服务器
安装httpd服务 yum install httpd -y
在httpd服务的默认发布目录/var/www/html下写一个默认发布页面。
13、 测试 :
真机(客户端)通过server1(varnish代理缓存服务器)访问server2(web服务器)的web资源
curl 172.25.70.1(server1的ip) 找的是server2:172.25.70.2的资源
- curl ip测试,此种测试会将默认页面的内容返回,不会做HTML的解析!
14、仍在server1上配置:在 /etc/varnish/defaults.cvl的路径下写入sub vcl_deliver模块
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);
}
15、 systemctl restart varnish 重启varnish服务
16、手动清除缓存
varnishadm ban req.url “~” / 清除所有缓存
varnishadm ban req.url “~” /index.html 仅清除index.html页面缓存
- curl -I 172.25.70.1/index.html 和curl -I 172.25.70.1 这两个命令所构建的http请求报文是不一样的
17、在**真机上**
curl -I 172.25.70.1 - X-Cache是varnish(squid)代理的自定义header,用来记录缓存的命中与否!
curl -I 172.25.70.1/index.html (未清除全部缓存)
2.3 搭建具有多个web后端服务器的varnish服务系统
1、在 server3(ip:172.25.70.3) 上,安装httpd服务,且编辑默认发布页面:
server3 bbs.ranran.org
2、在 server2(ip:172.25.70.2) 上,编辑默认发布页面:
server2 www.ranran.org
3、在 server1(ip:172.25.70.1)—varnish服务器 上,编辑 varnish核心配置文件/etc/varnish/default.vcl
在请求模块中,
加入两个后端的信息:
backend web1 {
.host = "172.25.70.2";
.port = "80";
}
backend web2 {
.host = "172.25.70.3";
.port = "80";
}
加入两个后端资源服务器域名:
if (req.http.host ~ "^(www.)?ranran.org") {
set req.http.host = "www.ranran.org";
set req.backend_hint = web1;
} elsif (req.http.host ~ "^bbs.ranran.org") {
set req.backend_hint = web2;
} else {
return (synth(405));
}
4、重启服务:systemctl restart varnish
5、在 真机 写入本地解析/etc/hosts:
6、在 真机 测试:curl www.ranran.org拿到的是web1的资源、curl bbs.ranran.org拿到的是web2的资源
实现了最基本的具有两台后端,但是两台后端之间没有任何关系
2.4 vainish加速器实现多个web后端服务器间的负载均衡
- 实际上企业当中的web后端服务器(为客户端提供资源的服务器)的性能有好有坏,性能差一点的就让它少干一点活,性能好的就多分担一点,现在假设就是server2这个web服务器性能比较差,server3这个服务器性能比较好,客户端通过varnish加速器访问server2的时候去轮询server3,实际上, 在企业中server2和server3上面存放的资源一模一样,只是为了实验效果明显起见,写为www.ranran.org和bbs.ranran.org。当客户端第一次访问server2的时候varnish去问server2要资源,当客户端第二次访问server2的时候varnish去问server3要资源,这个时候server2和server3上面的资源一模一样,客户端根本察觉不到,也缓解了server2(性能差)的访问压力。
- 这个思想就是在server2和server3之间实现调度(负载均衡),这个调度就是在varnish这个加速器上面实现的,实现负载均衡的调度算法很多,为了实验效果明显起见,我们使用轮询的方式均衡。
- 负载均衡的目的:就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,减轻服务器的压力,加快响应速度,保证:即使有一台服务机宕机,也能正常提供服务!
1、在 server1(ip:172.25.70.1)—varnish服务器 上,编辑 varnish核心配置文件/etc/varnish/default.vcl
- vcl4.0以后定义负载均衡需要导入模块:/usr/lib64/varnish/vmods/libvmod_directors.so
#vcl4.0以后定义负载均衡需要导入模块,一定要加在正确的位置,不能加在文件的最开头,要加在vcl4.0;下面
import directors from "/usr/lib64/varnish/vmods/libvmod_directors.so";
#定义负载均衡,加在backend web1/web2{...}之后
sub vcl_init {
new lb = directors.round_robin();
#说明:负载均衡所构成的集群,或者说lb的此套件中的负载均衡的服务器
lb.add_backend(web1);
lb.add_backend(web2);
}
#在访问web1的时候会使用负载均衡,在web1和web2之间进行轮询,在访问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
} elsif (req.http.host ~ "^bbs.westos.org") {
set req.backend_hint = web2;
} else {
return (synth(405));
# 405表示请求的方式不对,常见请求的方式有get、post、head、put!
# 404表示服务器响应了,但是服务器没有此资源,客户端的请求错误!
# 503表示服务器不存在,或者存在但没有开启服务!
}
}
2、重启服务:systemctl restart varnish
3、手动清理缓存: varnishadm ban req.url “~” /
4、此时,在 真机–客户端 上测试:curl www.ranran.org 会发现 访问web1时并没有轮询web2
- 出现此现象的原因,varnish加速器缓存了web1的资源,故 可在文件中加入return(pass),目的是不让varnish加速器缓存web服务器的资源,每次客户端请求,varnish加速器都会向web服务器要资源,如果缓存了就看不到负载均衡的效果。
5、在 server1(ip:172.25.70.1)—varnish服务器 上,编辑 varnish核心配置文件/etc/varnish/default.vcl , 重启服务:systemctl restart varnish
sub vcl_recv {
if (req.http.host ~ "^(www.)?westos.org") {
set req.http.host = "www.westos.org";
set req.backend_hint = lb.b:ackend();
return (pass); ##测试时可打开此选项,不进行缓存
} elsif (req.http.host ~ "^bbs.westos.org") {
set req.backend_hint = web2;
} else {
return (synth(405));
}
}
6、再次在 真机–客户端 上测试:curl www.ranran.org 会发现访问web1时轮询web2,访问web2时不轮询
2.5 搭建一varnish系统为具有多个资源的web后端服务器服务
背景 : 之前的web服务器中都只有一个资源, 实际在企业当中,比如百度的服务器:包括地图资源、新闻资源等等。 现在我也想实现一台主机上放多个资源,也就是给web服务器建立虚拟主机,然后结合varnish加速器。一个域名只能对应一个ip,但一个ip可以对应多个域名!
- 注意:配置某一后端服务器虚拟主机的配置和配置多个后端服务器的区别:
配置某一后端服务器虚拟主机 :将varnish服务器映射到同一后端服务器的不同IP,访问的其实还是同一台后端服务器(物理服务器)!
配置不同的后端服务器:将varnish服务器的的IP映射不同的域名,进而varnish根据访问的域名不同来访问不同的后端服务器!
1、在 server3(ip为172.25.70.3)web服务器上搭建apache虚拟主机
2、在 真机 上面进行测试
curl www.ranran.org(有两个资源)
- 因为真机的解析文件里面写的是server1的ip对应web1服务器的域名,故会去找web1服务器要东西,此时的web1服务器(server2)的资源一个是www.westos.org,一个是www(这个是轮询找的web2(server3)上面的资源)
curl bbs.westos.org
- 直接找到web2上面的bbs.westos.org, 可以清楚的看到,web2上有两个资源,一个是www,一个是bbs,www 可以和web1轮询,web2的bbs只用于web2。
2.6 CDN推送平台的搭建(图形化清理varnish代理服务器的缓存)
CDN推送: 当后端服务器中的内容有更新的时候,在varnish的缓存中应该及时的同步后端服务器中的内容。相当于清空varnish中的缓存,当下一次进行访问时,直接从服务器中获取新的内容。
在 server1(varnish服务器上)
1、安装服务:yum install -y unzip php httpd
2、unzip bansys.zip -d /var/www/html 下载banzip,然后解压,并安装到/var/www/html目录下,文件要直接暴露在/var/www/html目录中 == mv /var/www/html/bansys/ /var/www/html==*
3、编辑config.php写入被清理缓存的服务器信息
4、vim /etc/httpd/conf/httpd.conf
修改默认端口为8080并重启httpd systemctl start httpd,因为varnish已经占用了80端口。一个端口只能绑定一个服务或者说一个IP,否则端口被占用,会报错(服务无法启动)!
5、 在浏览器里面搜索:172.25.70.1:8080 ,选择HTTP
- bansys 有两种工作模式分别是:telnet 和 http 。
telnet模式需要关闭varnish服务管理端口的验证,注释掉/etc/sysconfig/varnish文件中的“-S ${VARNISH_SECRET_FILE}”这行,重启 varnish 服务即可。
http模式需要对 varnish 做以下设置:vim /etc/varnish/default.vcl
acl ranran {
"127.0.0.1"; #本机
"172.25.70.0"/24; #指定70网段的可以推送(有权限清理代理服务器上面的缓存)
}
sub vcl_recv {
if (req.method == "BAN") { # 如果采用推送方式是BAN
if (!client.ip ~ ranran) { # 如果客户端的IP不在ranran控制模块中,则不允许推送,并告知原因!
return(synth(405,"Purging not allowed for " + client.ip));
}
ban("req.url ~ " + req.url); # 匹配的话,就像命令行清除缓存一样来执行!
return(purge);
}
}
6、在真机进行测试:
- 注释:return(pass),这个会一直清除缓存
(1)curl -I www.ranran.org
然后图形化清除缓存,输入.*,发送(清除所有缓存)
再次 curl -I www.ranran.org 又是miss
(2)curl -I www.ranran.org/index.html
然后图形化清除缓存,输入/index ,发送(清除/index缓存)
再次 curl -I www.ranran.org/index.html ,又是miss