|  | 
 
| 把squid换成varnish来实现反向代理 www.varnish-cache.org
 client 张三
 |
 |
 varnish   李四
 |
 |
 web 王五   ftp  马六
 
 pass  当vcl_recv调用 pass 函数时,pass将当前请求直接转发到后端服务器。而后续的请求仍然通过varnish处理。
 pipe  而pipe模式则不一样,当vcl_recv判断 需要调用 pipe 函数时,varnish会在客户端和服务器之间建立一条直接的连接 ,之后客户端的所有请求都直接发送给服务器,绕过varnish,不再由varnish检查请求,直到连接断开。
 
 
 vcl_recv  --> vcl_pipe
 vcl_recv  --> vcl_pass
 vcl_recv  --> lookup (hash)  -->  vcl_miss --> vcl_fetch(vcl_backend_response) --> vcl_deliver
 vcl_recv  --> lookup (hash)  -->  vcl_hit  -->  vcl_deliver
 
 
 client 172.16.2.x
 |
 |
 172.16.2.35
 varnish
 192.168.1.1
 |
 |
 |---------------------|
 web1       web2
 192.168.1.128    192.168.1.129
 软件包路径在 笔记目录/program/varnish_soft/
 
 ----------------------------------------------
 4.0.3版本的源码编译安装方法(仅做参考,下面使用rpm版本来做)
 yum install pcre-devel
 tar xf docutils-0.12.tar.gz -C /usr/src/
 cd /usr/src/docutils-0.12/
 python setup.py install
 tar xf varnish-4.0.3.tar.gz -C /usr/src/
 cd /usr/src/varnish-4.0.3/
 ./configure --prefix=/usr/local/varnish
 make
 make install
 cp /usr/local/varnish/share/man/man7/vcl.7 /usr/share/man/man7/
 ------------------------------------------------
 4.0.3版本的rpm版安装方法:
 软件包路径如下(下载地址为http://repo.varnish-cache.org/redhat/varnish-4.0/el6/x86_64/varnish/和http://dl.fedoraproject.org/pub/epel/6Server/x86_64/)
 软件包主要为下面几个
 jemalloc-3.6.0-1.el6.x86_64.rpm
 varnish-4.0.3-1.el6.x86_64.rpm
 varnish-libs-4.0.3-1.el6.x86_64.rpm
 varnish-docs-4.0.3-1.el6.x86_64.rpm
 安装顺序
 # rpm -ivh jemalloc-3.6.0-1.el6.x86_64.rpm
 # rpm -ivh varnish-4.0.3-1.el6.x86_64.rpm varnish-libs-4.0.3-1.el6.x86_64.rpm varnish-docs-4.0.3-1.el6.x86_64.rpm
 
 配置rpm版varnish
 # vim /etc/sysconfig/varnish
 66 VARNISH_LISTEN_PORT=80 --这是listen的端口,默认为6081,我这里改为80(因为我的varnish在这里为最前端)
 69 VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1   --管理端口的监听地址,保持默认值
 70 VARNISH_ADMIN_LISTEN_PORT=6082 --管理端口,我这里保持默认值
 
 例1:varnish直接代理后台一个web服务器
 
 client 172.16.2.x
 |
 |
 172.16.2.35
 varnish
 192.168.1.1
 |
 |
 |
 web1
 192.168.1.128
 配置rpm版本主配置文件
 # vim /etc/varnish/default.vcl
 vcl 4.0;   --4.0.3版本,必须要加这一句指定为4.0版的vcl语法
 backend web1 {
 .host = "192.168.1.128";
 .port = "80";
 }
 
 启动varnish服务
 # /etc/init.d/varnish start
 (--或者直接使用命令来启动:# varnishd -f /etc/varnish/default.vcl -a 0.0.0.0:80 -s malloc -T 127.0.0.1:6082)
 # lsof -i:80
 # lsof -i:6082
 
 
 客户端可以通过elinks 172.16.2.35或者curl -I 172.16.2.35的方法来验证
 
 例2:varnish代理后台两个不同域名的web服务器
 client 172.16.2.x
 |
 |
 172.16.2.35
 varnish
 192.168.1.1
 |
 |
 |---------------------|
 web1       web2
 192.168.1.128    192.168.1.129
 www.aaa.com   www.bbb.com
 
 # vim /etc/varnish/default.vcl
 vcl 4.0;
 backend web1 {
 .host = "192.168.1.128";
 .port = "80";
 }
 backend web2 {
 .host = "192.168.1.129";
 .port = "80";
 }
 sub vcl_recv {
 if (req.http.host ~ "aaa.com$") {
 set req.backend_hint = web1;
 } else {
 set req.backend_hint = web2;
 }
 }
 --上面表示访问以aaa.com结尾的域名请求会给web1,bbb.com结尾的域名请求会给web2
 
 
 重启varnish服务
 # /etc/init.d/varnish restart
 
 测试
 在客户端
 cat /etc/hosts
 172.16.2.35 www.aaa.com
 172.16.2.35 www.bbb.com
 # elinks www.aaa.com/1   --访问此域名的都会显示web1的内容
 # elinks www.bbb.com/1  --都会显示web2的内容
 
 扩展,如果这两个网站是做的虚拟主机,那么依不同类型的虚拟主机(基于IP,基于端口,基于域名),配置方法不一样
 就基于域名的写法如下(基于IP和端口的就不例举了)
 backend web1 {
 .host = "192.168.1.128"; --这里用IP,也可以写www.aaa.com
 .port = "80";
 }
 backend web2 {
 .host = "192.168.1.128"; --这里用IP,也可以写www.bbb.com
 .port = "80";
 }
 
 例3:实现代理同一个网站内容分割,如www.aaa.com/sports/和www.aaa.com/news/会把请求分发给不同的后台web
 
 client 172.16.2.x
 |
 |
 172.16.2.35
 varnish
 192.168.1.1
 |
 |
 |---------------------|
 web1       web2
 192.168.1.128    192.168.1.129
 www.aaa.com/sports/ www.aaa.com/news/
 
 vcl 4.0;
 backend web1 {
 .host = "192.168.1.128";
 .port = "80";
 }
 backend web2 {
 .host = "192.168.1.129";
 .port = "80";
 }
 sub vcl_recv {
 if (req.url ~ "^/sports/") {
 set req.backend_hint = web1;
 }
 if (req.url ~ "^/news/") {
 set req.backend_hint = web2;
 }
 }
 
 扩展:上面是实现的url路径的负载分离,可以引出针对文件类型的分离(动静分离)
 只需要把
 sub vcl_recv {
 if (req.url ~ "\.(txt|html|css|jpg|jpeg|gif)$") { --在这里写上你想让它访问web1的文件类型就可以
 set req.backend_hint = web1 ;
 } else {
 set req.backend_hint = web2 ;
 }
 }
 
 例4:把www.xxx.com/sports/下的请求,使用rr算法分别调度给web1和web2
 
 vcl 4.0;
 backend web1 {
 .host = "192.168.1.128";
 .port = "80";
 }
 backend web2 {
 .host = "192.168.1.129";
 .port = "80";
 }
 import directors;
 sub vcl_init {
 new rr = directors.round_robin();
 rr.add_backend(web1);
 rr.add_backend(web2);
 }
 
 sub vcl_recv {
 if (req.url ~ "^/sports/") {
 set req.backend_hint = rr.backend();
 }
 if (req.url ~ "^/news/") {
 set req.backend_hint = web2;
 }
 }
 
 ------------------------------------------------------------
 
 例5,后台web服务器的健康检查
 
 vcl 4.0;
 probe backend_healthcheck {
 .url = "/test.txt";
 .timeout = 0.3 s;
 .window = 5;
 .threshold = 3;
 .initial = 3;
 }
 
 backend web1 {
 .host = "192.168.1.128";
 .port = "80";
 .probe = backend_healthcheck;
 }
 backend web2 {
 .host = "192.168.1.129";
 .port = "80";
 .probe = backend_healthcheck;
 }
 import directors;
 sub vcl_init {
 new rr = directors.round_robin();
 rr.add_backend(web1);
 rr.add_backend(web2);
 }
 sub vcl_recv {
 if (req.url ~ "^/sports/") {
 set req.backend_hint = rr.backend();
 }
 if (req.url ~ "^/news/") {
 set req.backend_hint = web2;
 }
 }
 
 ---------------------------------------
 综合配置实例:
 vcl 4.0;
 probe backend_healthcheck {
 .url = "/test.txt";
 .timeout = 0.3 s;
 .window = 5;
 .threshold = 3;
 .initial = 3;
 }
 
 backend web1 {
 .host = "192.168.1.128";
 .port = "80";
 .probe = backend_healthcheck;
 }
 backend web2 {
 .host = "192.168.1.129";
 .port = "80";
 .probe = backend_healthcheck;
 }
 import directors;
 sub vcl_init {
 new rr = directors.round_robin();
 rr.add_backend(web1);
 rr.add_backend(web2);
 }
 acl purgers {
 "127.0.0.1";
 "192.168.1.0"/24;
 }
 sub vcl_recv {
 if (req.method == "GET" && req.http.cookie) {
 return(hash);
 }
 if (req.url ~ "test.txt") {
 return(pass);
 }
 if (req.method == "PURGE") {
 if (!client.ip ~ purgers) {
 return(synth(405,"Method not allowed"));
 }
 return(hash);
 }
 if (req.http.X-Forward-For) {
 set req.http.X-Forward-For = req.http.X-Forward-For + "," + client.ip;
 } else {
 set req.http.X-Forward-For = client.ip;
 }
 
 if (req.http.host  ~ "www.cluster.com") {
 set req.backend_hint = rr.backend() ;
 } else {
 return(synth(404,"error domain name"));
 }
 }
 sub vcl_miss {
 return(fetch);
 }
 
 sub vcl_hit {
 if (req.method == "PURGE") {
 unset req.http.cookie;
 return(synth(200,"Purged"));
 }
 }
 
 sub vcl_backend_response {
 if (bereq.url ~ "\.(jpg|jpeg|gif|png)$") {
 set beresp.ttl = 10s;
 }
 if (bereq.url ~ "\.(html|css|js)$") {
 set beresp.ttl = 20s;
 }
 if (beresp.http.Set-Cookie) {
 return(deliver);
 }
 }
 
 sub vcl_deliver {
 if (obj.hits > 0) {
 set resp.http.X-Cache = "@_@ HIT from " + server.ip;
 } else {
 set resp.http.X-Cache = "@_@ oh,god,MISS";
 }
 }
 
 -----------------------------------------------------
 
 补充一:
 有一个问题:就是后台的web有大量的健康检查日志,如果配置的是每5秒一次检查的话,那么apache每5秒就会有这么一条;
 想要清除它的话
 # vim /etc/httpd/conf/httpd.conf
 SetEnvIf Request_URI "^/test\.txt$" dontlog --加上这一句
 CustomLog logs/access_log combined env=!dontlog --在你希望不记录与test.txt有关的日志后面加上env=!dontlog
 /etc/init.d/httpd restart
 
 那上面的方法与架构前端是varnish或squid或nginx或haproxy等无关,上面的配置是用的apache本身的参数
 
 当然如果你不会这种方法,也可以用笨方法,写一个脚本,定期或者在日志轮转前清除健康检查日志就可以了
 
 # vim clear_healtycheck_log.sh
 #!/bin/bash
 sed -i '/test.txt/d' /var/log/httpd/access_log
 kill -USR1 `cat /var/run/httpd/httpd.pid`
 
 --------------------------------------------------------------
 补充二:
 关于如何让后台的web服务器显示的IP是客户端的真实IP,而不是varnish的内网IP的做法
 
 首先在vanrish配置里有下面一段相关配置(在4.0.3版测试时,不要这一段也可以,说明应该默认配置就是这个)
 if (req.http.X-Forward-For) {
 set req.http.X-Forward-For = req.http.X-Forward-For + "," + client.ip;
 } else {
 set req.http.X-Forward-For = client.ip;
 }
 
 然后在后面的web服务器里做下面的修改
 # vim /etc/httpd/conf/httpd.conf
 LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" varnishcombined   --加上这一句,这是表示增加了一个日志格式,这个格式名为varnishcombined
 
 CustomLog logs/access_log varnishcombined env=!dontlog  --修改这一句,把原来它使用的combined格式换成varnishcombined格式
 
 # /etc/init.d/httpd  restart
 然后使用客户端去访问测试,后面apache显示的IP是客户端的真实IP了
 但是这里有一个问题:如果这次访问是第一次访问,日志里才会有;如果是被varnish命中了,则varnish直接返回给客户端了,所以后台的web这里就没有记录了
 
 另一个解决方法:
 那就是不使用后面的web的日志,而直接使用varnish的日志
 /etc/init.d/varnishncsa start  --启动varnish日志服务
 # cat /var/log/varnish/varnishncsa.log   --日志路径
 
 ======================================
 
 补充三:
 # varnishstat --查看一些参数指标
 
 =============================================================
 
 补充四:
 尝试使用ab压力测试
 
 非varnish的环境,测试准备
 1,先关闭varnish,然后写一条DNAT
 iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.128
 2,关闭web2,只留下web1,单网站测试
 3,在web1上route add default gw 192.168.1.1把网关指向varnish内网IP,主要是为了数据能够回去
 然后在客户使用下面命令来测试
 # ab -c 100 -n 1000 http://www.cluster.com/1.txt
 
 Server Software:        Apache/2.2.15
 Server Hostname:        www.cluster.com
 Server Port:            80
 Document Path:          /1.txt
 Document Length:        4 bytes
 Concurrency Level:      100
 Time taken for tests:   0.343 seconds
 Complete requests:      1000
 Failed requests:        0
 Write errors:           0
 Total transferred:      271000 bytes
 HTML transferred:       4000 bytes
 Requests per second:    2913.94 [#/sec] (mean)
 Time per request:       34.318 [ms] (mean)
 Time per request:       0.343 [ms] (mean, across all concurrent requests)
 Transfer rate:          771.17 [Kbytes/sec] received
 
 
 有varnish环境测试准备
 1,去掉上面的iptables,
 2,启动varnish
 然后在客户端测试
 # ab -c 100 -n 1000 http://www.cluster.com/1.txt
 
 Server Software:        Apache/2.2.15
 Server Hostname:        www.cluster.com
 Server Port:            80
 Document Path:          /1.txt
 Document Length:        4 bytes
 Concurrency Level:      100
 Time taken for tests:   0.103 seconds
 Complete requests:      1000
 Failed requests:        0
 Write errors:           0
 Total transferred:      377951 bytes
 HTML transferred:       4056 bytes
 Requests per second:    9729.05 [#/sec] (mean)
 Time per request:       10.278 [ms] (mean)
 Time per request:       0.103 [ms] (mean, across all concurrent requests)
 Transfer rate:          3590.92 [Kbytes/sec] received
 
 最后比较结果,结论是varnish处理速度比非varnish环境快(还可以与squid做个对比,varnish比squid也要快)
 
 | 
 |