套句马哥经常说的话,cache is king,在现在的企业架构中,都用到了缓存服务器,缓存,可以减轻对后端服务器的压力,而且对于请求比较频繁的热区数据,我们如果缓存在缓存服务器上,都会增加被命中的概率,对于大并发的请求情况下,对于后端的服务器也是一种保护。
下面我们要介绍的是缓存服务器中的新秀,varnish,这是一款轻量级的缓存服务,相比squid,性能更高,速度更快,管理上还更加方便,被说烂的例子就是挪威最大的在线报纸,用3台varnish替换掉了12台squid,性能上还有提升,可见varnish的地位上升之快。
varnish于nginx有着众多的相似之处,它们都是各自领域的新秀,而且,都是有一个master进程,多个子进程所构成,这次,我要利用varnish的缓存功能,加上haproxy的调度和高可用性,搭建一个高可用,且具有很强缓存的web服务
系统:CentOS 6.5
服务器数量:5台
所需要的软件及下载地址:
varnish-3.0.5-1.el6.x86_64.rpm
varnish-libs-3.0.5-1.el6.x86_64.rpm
https://repo.varnish-cache.org/redhat/varnish-3.0/el6/x86_64/varnish/
haproxy.x86_64 0:1.4.24-2.el6 #通过yum安装
首先,我们先在node3、和node4这两个主机上,提供web服务,提供主页
node3上:
[root@node3 ~]# cat /var/www/html/index.html <h1>I am a linux lover</h1>
node4上:
[root@node4 ~]# cat /var/www/html/index.html <h1>shell is difficult to learn</h1>
然后,将这两个web服务启动
[root@node3 ~]# service httpd start [root@node4 ~]# service httpd start
后端的web服务已完成,下面就是搭建我们的varnish缓存服务器了
在node1和node2上都执行下列操作
[root@node1 ~]# yum install varnish-libs-3.0.5-1.el6.x86_64.rpm varnish-3.0.5-1.el6.x86_64.rpm #可以自动解决依赖关系
备份varnish的配置文件
[root@node1 ~]# cp /etc/varnish/default.vcl /etc/varnish/default.vcl.bak
编辑varnish的启动脚本的配置文件,让其监听在80端口上,而且,指定存储类型为mallo
VARNISH_LISTEN_PORT=80 #监听在80端口 VARNISH_STORAGE_SIZE=100M #缓存大小为100M VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}" #这里是调用上面的变量
然后,启动varnish服务
[root@node2 ~]# service varnish start [root@node1 ~]# ss -tlnp | grep 80 #此时,80端口已经被监听(最好确保我们的其他web程序是关闭的) LISTEN 0 128 :::80 :::* users:(("varnishd",8840,8)) LISTEN 0 128 *:80 *:* users:(("varnishd",8840,7))
登录到我们的varnish的控制端查看
[root@node2 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
-S:指定密钥文件
-T:指定可以登录的管理员的地址和端口,这个是在/etc/sysconfig/varnish文件中定义的
实验要求:(对varnish而言)
1、要通过负载均衡的方式调度后端的两个web服务器
2、可以在后端的web服务器的日志文件上,查看真正访问web服务的客户端的IP地址
3、实现对后端两个web服务器健康状态的检测
使用轮询的调度方法
在/etc/varnish/目录中新建一个lb.vcl的文件,作为负载均衡作用的配置文件,配置如下
backend web1 { .host = "192.168.77.13"; .port = "80"; } backend web2 { .host = "192.168.77.14"; .port = "80"; } director webs round-robin { #使用轮询的调度算法 {.backend = web1;} {.backend = web2;} } sub vcl_recv { set req.backend = webs; #要调用上面这个组 }
然后,我们可以通过上面的管理接口,使用这个配置文件了
varnish> vcl.load lb ./lb.vcl #加载这个配置 200 VCL compiled. #这样就是编译成功的提示 varnish> vcl.use lb #使用上面定义的配置 200
此时,我们在浏览器中测试,先访问node1,再访问node2
之后,无论怎么刷新都不改变了,调出开发者工具查看
我们可以查看我们的后端web服务器的日志文件
[root@node4 ~]# tail /var/log/httpd/access_log 192.168.77.12 �C - [20/Sep/2014:20:32:28 +0800] "GET /favicon.ico HTTP/1.1" 404 288 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" 192.168.77.11 �C - [20/Sep/2014:20:35:23 +0800] "GET / HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
此时,显示的是我们的varnish服务器的地址
在后端记录客户端IP地址
更改配置文件,使其能够记录客户端的IP地址,在上面的实验上扩展
[root@node1 varnish]# cp lb.vcl log.vcl [root@node1 varnish]# vim log.vcl backend web1 { .host = "192.168.77.13"; .port = "80"; } backend web2 { .host = "192.168.77.14"; .port = "80"; } director webs round-robin { {.backend = web1;} {.backend = web2;} } sub vcl_recv { set req.http.X-Forwarded-For = clinet.ip; if (req.url ~ "index.html$") { return (pass); } set req.backend = webs; }
两个web服务器都做修改
然后,将后端的web记录日志的格式修改如下
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
重启httpd服务
[root@node3 ~]# service httpd restart
回到varnish服务器,加载新的配置
varnish> vcl.load log ./log.vcl 200 VCL compiled. varnish> vcl.use log 200
到浏览器中,分别访问
发现,网页发生了变化,这是缓存时间结束了,新的请求返回新的网页,之后,连续刷新时,就不会缓存了
查看我们后端web服务器的日志文件
[root@node3 ~]# tail /var/log/httpd/access_log 192.168.77.11 �C - [20/Sep/2014:20:35:24 +0800] "GET /favicon.ico HTTP/1.1" 404 288 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" [root@node4 ~]# tail /var/log/httpd/access_log 192.168.77.1, 192.168.77.1 �C - [20/Sep/2014:20:54:51 +0800] "GET / HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
此时,上面记录的都是当前windows主机的地址了,如果没有,可以多次刷新网页后查看,可能还是缓存命中
健康检查机制:
如果,我们的后端web宕机了呢?我们是否发觉?下面引入健康检查机制
[root@node1 varnish]# cp log.vcl health.vcl [root@node1 varnish]# vim health.vcl probe healthchk { #定义一个健康检测的标准 .url = "/"; .interval = 5s; .timeout = 2s; } backend web1 { .host = "192.168.77.13"; .port = "80"; .probe = healthchk; #调用健康检测 } backend web2 { .host = "192.168.77.14"; .port = "80"; .probe = healthchk; } director webs round-robin { {.backend = web1;} {.backend = web2;} } sub vcl_recv { set req.http.X-Forwarded-For = client.ip; if (req.url ~ "index.html$") { return (pass); } set req.backend = webs; }
加载新的配置,并使用
varnish> vcl.load health ./health.vcl 200 VCL compiled. varnish> vcl.use health 200
此时,我们可以将后端的两个web服务器的http服务都停掉
[root@node4 ~]# service httpd stop
在我们的浏览器中查看
此时,健康状态就显示出来了,不过,你可能要等缓存失效后,才能刷出这个网页
最后,我们可以在前端加上一个haproxy,作为这两个varnish缓存服务器的负载均衡器
安装haproxy,这里使用yum的方式
[root@hap ~]# yum install -y haproxy
备份配置文件,并且对配置文件进行编辑
[root@hap ~]# cd /etc/haproxy/ [root@hap haproxy]# cp haproxy.cfg haproxy.cfg.bak [root@hap haproxy]# vim haproxy.cfg frontend main *:80 maxconn 3000 default_backend webs backend webs balance uri server varnish1 192.168.77.11 check port 80 server varnish2 192.168.77.12 check port 80 server back 127.0.0.1:8080 backup stats enable #开启status功能 stats admin if TRUE #开启管理功能 stats hide-version #隐藏版本号 stats scope . #当前作用域 stats uri /admin?stas #自定义uri stats realm admin\ authorizen #用户认证模式 stats auth hapadmin:varnish #认证的用户名和密码
然后,启动haproxy服务
[root@hap haproxy]# service haproxy start [root@hap haproxy]# ss -tlnp | grep 80 #此时,已经监听80端口 LISTEN 0 128 *:80 *:* users:(("haproxy",2497,4))
将后端的两个web服务启动,然后,在浏览器中访问
此时,还可以查看我们的status状态页
此时,我们还可以提供sorry server,即这里的back,在haproxy的本机上
[root@hap haproxy]# cat /var/www/html/index.html <h1>Sorry! please wait!</h1>
同时,还得修改httpd的配置文件,使其监听在8080端口上,因为80被haproxy占用
[root@hap haproxy]# vim /etc/httpd/conf/httpd.conf Listen 8080 #修改此项 并且,把http服务启动 [root@hap haproxy]# service httpd start
我们可以在stats页面上,让后端的两个varnish服务器停止工作,刷浏览器
访问我们的站点
当后端主机宕机后,我们的haproxy上的sorry server就能派的上用场了,详细的varnish的内容会在近期的varnish原理知识中发布出来,这也是自己的任务。