在Linux中的squid介绍及其简单配置(正向代理、反向代理博文中,我们已经详细介绍过正向代理和反向代理,其都是利用squid实现的,本次,我们将介绍利用varnish实现反向代理,从而搭建CDN缓存体系。
CDN的基本原理为反向代理,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个节点服务器。通过部署更多的反向代理服务器,来达到实现多节点CDN的效果。
下面让我们看看访问使用CDN缓存后的网站的过程:
通过上图,我们可以了解到,使用了CDN缓存后的网站的访问过程变为:
1)、用户向浏览器提供要访问的域名;
2)、浏览器调用域名解析库对域名进行解析,由于CDN对域名解析过程进行了调整,所以解析函数库一般得到的是该域名对应的CNAME记录,为了得到实际IP地址,浏览器需要再次对获得的CNAME域名进行解析以得到实际的IP地址;在此过程中,使用的全局负载均衡DNS解析,如根据地理位置信息解析对应的IP地址,使得用户能就近访问。
3)、此次解析得到CDN缓存服务器的IP地址,浏览器在得到实际的IP地址以后,向缓存服务器发出访问请求;
4)、缓存服务器根据浏览器提供的要访问的域名,通过Cache内部专用DNS解析得到此域名的实际IP地址,再由缓存服务器向此实际IP地址提交访问请求;
5)、缓存服务器从实际IP地址得得到内容以后,一方面在本地进行保存,以备以后使用,另一方面把获取的数据返回给客户端,完成数据服务过程;
6)、客户端得到由缓存服务器返回的数据以后显示出来并完成整个浏览的数据请求过程
Varnish是高性能开源的反向代理服务器和HTTP缓存服务器,Varnish的功能与Squid服务器相似,都可以用来做HTTP缓存。
Squid是从硬盘读取缓存的数据,而Varnish把数据存放在内存中,直接从读取内存,避免了频繁在内存、磁盘中交换文件,所以Varnish要相对更高效,但也有缺点,内存中的缓存在服务器重启后会丢失。
varnish启动时会产生2个进程,一个由root开启(主进程),一个由varnish开启(子进程);主进程 fork 子进程,主进程等待子进程的信号,子进程退出后,主进程重新启动子进程。
子进程生成若干线程,具体对客户的请求进行处理:
Accept 线程:监听端口,接受连接;接受连接后组成 session 结构,查看是否有空闲线程,若有则分配给其处理,若无,则检查等待队列 overflow 的大小,若过大,则抛弃请求,否则加入 overflow 队列。
Work 线程:从对列上摘除请求,对请求进行处理,直到完成,然后处理下一个请求。子进程会为每一个用户请求(如果需要处理),启一个worker线程,所以它单线程,单响应的;即是每一个请求用一个独立的线程响应的
Epoll 线程: 一个请求处理称作一个 session,在 session 周期内,处理完请求后,会交给Epoll 处理,监听是否还有事件发生。
Expire 线程:对于缓存的对象,根据过期时间,组织成二叉堆,该线程周期检查该堆的根,处理过期的文件
Varnish 的master进程负责启动工作,master进程读取配置文件,根据指定的空间大小(例如管理员分配了2G内存)来创建存储空间,创建并管理child进程,child进程来处理后续任务,它会分配一些线程来执行不同的工作,例如:
接受http请求
为缓存对象分配存储空间
清除过期缓存对象
释放空间 碎片整理
Varnish Configuration Language(VCL)是varnish配置缓存策略的工具,它是一种基于“域”的简单变成语言,它支持有限的算术运算和逻辑运算操作、允许使用正则表达是进行字符串匹配、允许用户使用set自定义变量、支持if判断语句,也有内置的函数和变量等。使用VCL编写的缓存策略通常保存至.vcl文件中,其需要编译成二进制的格式后才能由varnish调用
vcl处理过程:
(1)Receive 状态,也就是请求处理的入口状态,根据 VCL 规则判断该请求应该是 Pass 或Pipe,或者进入 Lookup(本地查询)。
(2)Lookup 状态,进入此状态后,会在 hash 表中查找数据,若找到,则进入 Hit 状态,否则进入 miss 状态。
(3)Pass 状态,在此状态下,会进入后端请求,即进入 fetch 状态。
(4)Fetch 状态,在 Fetch 状态下,对请求进行后端的获取,发送请求,获得数据,并进行本地的存储。
(5)Deliver 状态, 将获取到的数据发送给客户端,然后完成本次请求。
(1)所需环境:
使用上篇博客中利用母盘快照的生成的三台主机,其中一台作为Varnish部署主机,两台作为后台服务器,真机作为客户端测试机
server1 172.25.2544.101 ##Varnish部署主机
server2 172.25.254.102 ##后台服务器
server3 172.25.254.103 ##后台服务端
fpundation72.ilt.example.com 172.25.254.72 ##客户端
(2)Varnish部署主机安装软件:
[root@server1 ~]#yum install jemalloc-3.6.0-1.el7.x86_64.rpm
varnish-libs-4.0.5-1.el7.x86_64.rpm varnish-4.0.5-1.el7.x86_64.rpm
[root@server1 ~]# rpm -qc varnish-4.0.5-1.el7.x86_64 # 查看varnish在系统中生成的文件
/etc/logrotate.d/varnish
/etc/varnish/default.vcl #varnish配置文件
/etc/varnish/varnish.params #varnish的参数文件
(3)查看varnish的服务文件
可以查看varnish服务中设定的最大开启文件数量以及锁定的内存大小:
Varnish打开的最大文件数限制为131072
Varnish锁定的共享内存大小为82M
vim /usr/lib/systemd/system/varnish.service
sysctl -a | grep file # 查看本机系统最大文件访问数量
由于系统最大文件访问数量不满足varnish要求,所以此时更改虚拟机配置,增加内存至2048M,修改后重新查看系统最大连接文件数可以满足varnish的需要
(5)编辑varnish用户的限制文件(与varnish配置文件中限制相对应),并且开启varnish
vim /etc/security/limits.conf # 编辑该文件,将最大文件访问数以及锁定的内存大小写入文件最后
systemctl start varnish
root@server1 ~]# vim /etc/varnish/varnish.params ##在该文件中编辑更改端口为80
[root@server1 ~]# vim /etc/varnish/default.vcl # 编辑varnish主配置文件
[root@server1 ~]# systemctl restart varnish
(1)在172.25.254.102主机安装http,并在其发布目录中写入内容用来测试,作为后台服务器
(2)测试:使用客户端主机直接访问varnish代理服务器,可以得到后台服务器中的内容:
[kiosk@foundation72 ~]$ curl 172.25.254.101 #使用curl命令来获取代理服务端页面内容
server1-test.example.com #可以访问后台服务端
[kiosk@foundation72 ~]$
(3)查看缓存命中情况
作为varnish代理端,在配置文件中添加了后端服务器的ip及端口,在访问代理端的时候实际是在访问后端服务器,则第一次访问会产生缓存,下一次访问的时侯则由缓存服务器直接响应客户端需求,减少延时。
修改配置文件,在缓存数据时发送信息给客户端(查看缓存命中情况),根据数据是来自后端服务器还是来自缓存的内容,返回不同的消息给客户端主机
vim /etc/varnish/default.vcl #编辑配置文件
vcl_deliver为在缓存数据将要发送到客户端时调用的子进程。
客户端测试结果如下:
[kiosk@foundation72 ~]$ curl -I 172.25.254.101
HTTP/1.1 200 OK
Date: Fri, 19 Jul 2019 15:12:56 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Fri, 19 Jul 2019 14:50:40 GMT
ETag: "19-58e09d9a58310"
Content-Length: 25
Content-Type: text/html; charset=UTF-8
X-Varnish: 2
Age: 0
Via: 1.1 varnish-v4
X-Cache: MISS from westos cache #未命中,访问后台服务端
Connection: keep-alive
[kiosk@foundation72 ~]$ curl -I 172.25.254.101
HTTP/1.1 200 OK
Date: Fri, 19 Jul 2019 15:12:56 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Fri, 19 Jul 2019 14:50:40 GMT
ETag: "19-58e09d9a58310"
Content-Length: 25
Content-Type: text/html; charset=UTF-8
X-Varnish: 32770 3
Age: 6
Via: 1.1 varnish-v4
X-Cache: HIT from westos cache #命中,访问代理服务端
Connection: keep-alive
[kiosk@foundation72 ~]$ curl -I 172.25.254.101
HTTP/1.1 200 OK
Date: Fri, 19 Jul 2019 15:12:56 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Fri, 19 Jul 2019 14:50:40 GMT
ETag: "19-58e09d9a58310"
Content-Length: 25
Content-Type: text/html; charset=UTF-8
X-Varnish: 5 3
Age: 10 #命中,访问代理服务端
Via: 1.1 varnish-v4
X-Cache: HIT from westos cache
Connection: keep-alive
(4)通过 varnishadm 手动清除缓存
varnishadm ban req.url "~" / # 清理所有的缓存
varnishadm ban req.url "~" /index.html # 对指定文件的缓存进行清理
缓存清理后,则需要先访问后台服务端,再将其缓存
[kiosk@foundation72 ~]$ curl -I 172.25.254.101
HTTP/1.1 200 OK
Date: Fri, 19 Jul 2019 15:19:32 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Fri, 19 Jul 2019 14:50:40 GMT
ETag: "19-58e09d9a58310"
Content-Length: 25
Content-Type: text/html; charset=UTF-8
X-Varnish: 7
Age: 0
Via: 1.1 varnish-v4
X-Cache: MISS from westos cache
Connection: keep-alive
[kiosk@foundation72 ~]$ curl -I 172.25.254.101
HTTP/1.1 200 OK
Date: Fri, 19 Jul 2019 15:19:32 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Fri, 19 Jul 2019 14:50:40 GMT
ETag: "19-58e09d9a58310"
Content-Length: 25
Content-Type: text/html; charset=UTF-8
X-Varnish: 32772 8
Age: 2
Via: 1.1 varnish-v4
X-Cache: HIT from westos cache
Connection: keep-alive
在使用不同的域名访问同一台代理服务器的时候,可以进行设置,将请求由发送到不同的后端服务器。
需要在代理服务器的varnish配置文件中设置多个后端服务器,并在vcl_recv 子程序中设置对不同的域名请求发送到不同的后端服务器。
(1)设置server2和server3都作为后台服务端,配置代理端的配置文件
vim /etc/varnish/default.vcl # 编辑配置文件
[root@server3 ~]# cd /var/www/html
[root@server3 html]# ls
[root@server3 html]# vim index.html
[root@server3 html]# cat index.html
bbs.westos.com
(3)客户端中写入解析并测试
[root@foundation72 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.233 www.westos.com
172.25.254.101 www.westos.org bbs.westos.org
[root@foundation72 ~]# curl www.westos.org
www.westos.com
[root@foundation72 ~]# curl bbs.westos.org
bbs.westos.com
当某台后端服务器的访问压力过大的时候,可以设置多台后端服务器,提供相同的内容服务,将客户请求分配给多台服务器,减缓一台服务器的压力。
可以把多台 backends 聚合成一个组,这些组被叫做 directors。这样可以增强性能和弹力。
设置访问web1时,轮询访问172.25.254.102和172.25.254.103;访问web2时访问172.25.254.103
return(pass)是设置直接将请求发送到后端服务器,并且不缓存返回的内容,如果进行缓存,再次访问的时候就会直接从缓存中提取内容,轮询的效果就不明显
vim /etc/varnish/default.vcl # 编辑配置文件
测试:
为了效果明显,在web1和web2中设置的内容不一致,实际应用中,这两台服务器中提供的内容服务应该一致。
[root@foundation72 ~]# curl www.westos.org
www.westos.com
[root@foundation72 ~]# curl www.westos.org
bbs.westos.com
[root@foundation72 ~]# curl bbs.westos.org
bbs.westos.com
在后端服务上设置虚拟主机,当不同的域名被发送到同一个后端服务器,可以让其访问不同的内容。
就例如:在以上设置中,当采用轮询时,两个域名都会访问server3,如果没有虚拟机,两个域名访问server3时都会显示都一样的默认发布页面。因此,在server3中设置虚拟主机
vim /etc/httpd/conf.d/vhost.conf # 设置虚拟主机
DocumentRoot /www
ServerName www.westos.org
Require all granted
DocumentRoot /bbs
ServerName bbs.westos.org
Require all granted
[root@server3 html]# mkdir /www
[root@server3 html]# mkdir /bbs
[root@server3 html]# vim /www/index.html
[root@server3 html]# cat /www/index.html
server3:www.westos.com
[root@server3 html]# vim /bbs/index.html
[root@server3 html]# cat /bbs/index.html
server3:bbs.westos.com
客户端测试:可以看到不同域名访问同一后台服务器时,显示不同内容
为了更加快捷方便及时对代理服务器中缓存内容进行清理更新。可以在代理服务器上设置网络推送页面,直接在网页上推送平台对代理服务器缓存进行修改。
(1) 代理服务器上安装php 以及http
由于推送平台使用的是php进行编写,需要安装php插件识别php脚本内容
[root@server1 ~]# yum install php httpd -y
更改http端口为8080,80默认端口已经被varnish占用,当以相同断空进行访问时会因为端口冲突而失败。修改完成后启动httpd服务。
[root@server1 conf.d]# cd /etc/httpd/conf
[root@server1 conf]# ls
httpd.conf magic
[root@server1 conf]# vim httpd.conf
[root@server1 conf]# systemctl restart httpd
[root@server1 ~]# ls
bansys.zip varnish-4.0.5-1.el7.x86_64.rpm
jemalloc-3.6.0-1.el7.x86_64.rpm varnish-libs-4.0.5-1.el7.x86_64.rpm
[root@server1 ~]# unzip bansys.zip -d /var/www/html
[root@server1 ~]# cd /var/www/html
[root@server1 html]# ls
bansys
[root@server1 html]# mv bansys/* /var/www/html
[root@server1 html]# ls
bansys class_socket.php config.php index.php purge_action.php static
(3) 修改推送平台配置文件:
[root@server1 html]# vim config.php
(4) 修改varnish配置文件:
vim /etc/varnish/default.vcl # 编辑配置文件
acl westos { #设置访问控制
"127.0.0.1";
"172.25.31.0"/24;
}
sub vcl_recv {
if (req.method == "BAN") {
if (!client.ip ~ westos) { # 如果客户请求ip不是指定的网段
return(synth(405,"Purging not allowed for " + client.ip)); # 发送一个405错误
}
ban("req.url ~ " + req.url); # 客户请求的ip是指定网段,对缓存内容进行更新
return(purge);
}
}
systemctl restart varnish # 重启服务
(5)测试:在客户端访问,使代理服务器缓存内容
curl -I www.westos.org
curl -I www.westos.org/index.html
客户端进行测试:http://172.25.254.72:8080,有两种工作模式,分别是:telnet 和 http 模式。选择HTTP模式,CDN群组中选择www.westos.com群组,推送内容中可以写入(.*)清理全部缓存或(/index.html)清除指定页面