一、简介

Varnish是一个cache型的HTTP反向代理。Varnish的核心功能是能能将后端web服务器返回的结果缓存起来,如果发现后续有相同的请求,Varnish将不会将这个请求转发到web服务器,而是返回缓存中的结果。这将有效的降低web服务器的负载,提升响应速度,并且每秒可以响应更多的请求。Varnish速度很快的另一个主要原因是其缓存全部都是放在内存里的,这比放在磁盘上要快的多。避免了Squid频繁在内存、磁盘中交换文件的缺点。


二、安装

1. 添加varnish用户

[root@varnish ~]# groupadd -r varnish
[root@varnish ~]# useradd -r -M -s /sbin/nologin -g varnish varnish


2. 安装varnish软件

[root@varnish ~]# yum install -y gcc gcc-c++ pcre-devel make ncurses* libedit*
[root@varnish ~]# tar xf varnish-3.0.5.tar.gz
[root@varnish ~]# cd varnish-3.0.5
[root@varnish varnish-3.0.5]# ./configure --prefix=/usr/local/varnish \
--enable-debugging-symbols \
--enable-developer-warnings \
--enable-dependency-tracking
[root@varnish varnish-3.0.5]# make
[root@varnish varnish-3.0.5]# make install


3. 拷贝varnish启动所需的配置文件

[root@varnish varnish-3.0.5]# cp redhat/varnish_reload_vcl /usr/local/varnish/bin/
[root@varnish varnish-3.0.5]# cp redhat/varnish.sysconfig /etc/sysconfig/varnish
[root@varnish varnish-3.0.5]# cp redhat/varnish.initrc /etc/init.d/varnish
[root@varnish varnish-3.0.5]# chkconfig --add varnish
[root@varnish varnish-3.0.5]# chkconfig varnish on


4. 完善安装(可以不做)

[root@varnish ~]# vim /etc/profile
export PATH=$PATH:/usr/local/varnish/bin/  #最后添加这一行
[root@varnish ~]# vim /etc/man.config
MANPATH /usr/local/varnish/share/man    #添加这一行


5. 简单配置,让varnish足以成功启动

1)配置/etc/sysconfig/varnish这个配置文件

[root@varnish ~]# vim /etc/sysconfig/varnish
## Alternative 3, Advanced configuration
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/usr/local/varnish/etc/varnish/default.vcl
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=
VARNISH_LISTEN_PORT=80
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
#
# # Shared secret file for admin interface
VARNISH_SECRET_FILE=/usr/local/varnish/etc/varnish/secret
#
# # The minimum number of worker threads to start
VARNISH_MIN_THREADS=50
#
# # The Maximum number of worker threads to start
VARNISH_MAX_THREADS=1000
#
# # Idle timeout for worker threads
VARNISH_THREAD_TIMEOUT=120
#
# # Cache file location
#VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
#
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
VARNISH_STORAGE_SIZE=1G
#
# # Backend storage specification
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"
#
# # Default TTL used when the backend does not specify one
VARNISH_TTL=120
#
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"
#

/etc/init.d/varnish中的变量$DAEMON_OPTS就是在这个配置文件中设置的,这个变量其实就是指定varnishd这个进程启动的一些参数,这个配置文件中一共包括了4个可供选择的模版,这里就用第3个高级配置

VARNISH_VCL_CONF用于指定配置文件的位置

VARNISH_LISTEN_PORT=80指定varnish监听的端口

VARNISH_ADMIN_LISTEN_ADDRESS指定管理接口监听的地址

VARNISH_ADMIN_LISTEN_PORT指定管理接口监听的端口

VARNISH_SECRET_FILE指定管理接口的密码文件

VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"其中malloc是一个函数,用户分配内存空间的


2)修改启动脚本

[root@varnish ~]# vim /etc/init.d/varnish
exec="/usr/local/varnish/sbin/varnishd"
reload_exec="/usr/local/varnish/bin/varnish_reload_vcl"


3)修改默认配置文件

[root@varnish ~]# vim /usr/local/varnish/etc/varnish/default.vcl
backend default {
     .host = "172.16.1.20";
     .port = "80";
}
#指定需要代理的主机的IP地址和端口号


4)生成secret文件

[root@varnish ~]# echo -n "zhuftd" | md5sum > /usr/local/varnish/etc/varnish/secret
[root@varnish ~]# chmod 644 /usr/local/varnish/etc/varnish/secret


5)修改reload文件

[root@varnish ~]# vim /usr/local/varnish/bin/varnish_reload_vcl
74 VARNISHADM="/usr/local/varnish/bin/varnishadm $secret -T $VARNISH_ADMIN_LISTEN_ADDRESS:$VARNISH_ADMIN_LISTE
    N_PORT"


6. 启动varnish

[root@varnish ~]# service varnish start
Starting Varnish Cache:                                    [  OK  ]
[root@varnish ~]# service varnish status
varnishd (pid  11276) is running...


二、varnish的处理流程

wKioL1MtgGyw-kgHAALhcNyQbOU459.jpg

主要的动作:

pass: varnish将请求转发给后端服务器。

lookup: 从hash表中查找数据。

pipe: 在client和backend之间建立一条连接,varnish不会看它们之间传送的数据。由于HTTP1.1中一个连接可以传输客户端的多个请求,所以应该通知varnish增加一个"Connection: close"的头部。

deliver: 将获取到的数据发送给客户端,完成本次请求。


VCL支持的运算符:

=赋值运算符
==对比
~
匹配,可以基于正则表达式匹配
!
逻辑非
&&
逻辑与
||
逻辑或


VCL中3个重要的数据结构(Requests, responses and objects)

req

从客户端过来的请求

req.backend

指定对应的后端主机

req.http.x-forwarded-for

http请求中的源地址

req.http.Authorization

http请求中的用户认证信息

req.request

指定请求的类型,例如GETHEADPOST

req.url

指定请求的地址

req.http.Cookie

http请求中的cookie信息

req.http.host

客户端请求的域名或者IP地址

req.restarts

表示请求重试的次数

beresp

从代理的服务器端返回的响应


beresp.url

后端服务器返回数据的url,可以根据这个url匹配正则表达式,然后设置不同的缓存时间

beresp.ttl

表示缓存的生存周期,也就是cache保留多长时间,单位是秒

obj

存储的cache中的对象

obj.status

表示返回内容的请求状态代码

obj.response

表示返回内容的请求状态信息

wKiom1MuP7XRcvv_AAB0Cmo4rEo790.jpg

这个的意思是当http请求中包含认证信息和cookie时,直接转发给后端的服务器(nginxapache等),因为当第一个用户成功认证以后,如果varnish缓存了这个信息,那么所有的其他客户端的请求将不需要认证。


三、后端服务器配置

1. 服务器配置

probe health {               #配置健康检测
    .url = "/index.html";    #varnish检测的页面
    .interval = 10s;         #检测的间隔时间
    .timeout = 30ms;         #检测的超时时间
    .window = 5;             #varnish会维持5个结果
    .threshold = 3;          #至少有3次window检测是成功的,才算健康
}       
backend web1 {                          #定义后端服务器1
     .host = "172.16.1.20";
     .port = "80";
     .probe = health;                   #调用健康模版
     .connect_timeout = 1s;             #等待连接后端服务器的时间
     .first_byte_timeout = 5s;          #等待backend传输过来第一个字节的时间
     .between_bytes_timeout = 2s;       #传输时字符之间的时间间隔
}
backend web2 {                        #定义后端服务器2
     .host = "172.16.1.40";
     .port = "80";
     .probe = health;
     .connect_timeout = 1s;
     .first_byte_timeout = 5s;
     .between_bytes_timeout = 2s;
}

配置完成之后还需在vcl_recv子模块中调用

sub vcl_recv {
 if (req.http.host ~ "www\.aa\.com"){
        set req.backend = web1;}
 else{
        set req.backend = web2;}
}


2. 负载均衡

director myLB round-robin {
     { .backend = web1; }
     { .backend = web2; }
}
sub vcl_recv {
        set req.backend = myLB;
}
#当然负载均衡的调度机制不是只有round-robin,还有random、DNS等


3. 访问控制

acl purge {
       "localhost";
       "127.0.0.1";
       "172.16.1.0"/24;
}   
sub vcl_recv {
       if (req.request == "PURGE") {
            if (!client.ip ~ purge) {
                   error 405 "Not allowed.";
                     }
               lookup;
             }
}


四、内核参数优化

[root@varnish ~]# vim /etc/sysctl.conf
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000 65000

net.ipv4.tcp_fin_timeout这个参数表示当服务器指定关闭连接时,socket保持在FIN-WAIT-2状态的最大时间。

net.ipv4.tcp_keepalive_time这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。默认是2小时,若将其设置得小一些,可以更快地清理无效的连接。

net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击。

net.ipv4.tcp_tw_reuse = 1表示允许将TIME-WAIT状态的socket重新用于新的TCP连接。

net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收。

net.ipv4.ip_local_port_range这个参数定义了在UDP和TCP连接中本地(不包括连接的远端)端口的取值范围。


五、管理

1.varnishadm

[root@varnish ~]# varnishadm -T 127.0.0.1:6082 -S /usr/local/varnish/etc/varnish/secret
200      
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-358.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-3.0.5 revision 1a89b1f
Type 'help' for command list.
Type 'quit' to close CLI session.
varnish> help


2. varnishlog

[root@varnish ~]# varnishlog
    0 Backend_health - web1 Still healthy 4--X-RH 5 3 5 0.001350 0.001759 HTTP/1.1 200 OK
    0 Backend_health - web2 Still healthy 4--X-RH 5 3 5 0.003149 0.002433 HTTP/1.1 200 OK
    9 SessionOpen  c 172.16.1.254 53905 0.0.0.0:80
    9 ReqStart     c 172.16.1.254 53905 19241885
    9 RxRequest    c GET
    9 RxURL        c /
    9 RxProtocol   c HTTP/1.1
    9 RxHeader     c Accept: text/html, application/xhtml+xml, */*
    9 RxHeader     c Accept-Language: zh-CN
    9 RxHeader     c User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)
    9 RxHeader     c Accept-Encoding: gzip, deflate
    9 RxHeader     c Host: 172.16.1.30
    9 RxHeader     c If-Modified-Since: Tue, 04 Mar 2014 05:08:34 GMT
    9 RxHeader     c If-None-Match: "40085-5-4f3c0e55fb165"
    9 RxHeader     c DNT: 1
    9 RxHeader     c Connection: Keep-Alive
    9 VCL_call     c recv lookup
    9 VCL_call     c hash
    9 Hash         c /
    9 Hash         c 172.16.1.30
    9 VCL_return   c hash
    9 Hit          c 19241876
    9 VCL_call     c hit deliver
    9 VCL_call     c deliver deliver
    9 TxProtocol   c HTTP/1.1
    9 TxStatus     c 304              #表示从缓存中取的数据
    9 TxResponse   c Not Modified
    9 TxHeader     c Server: Apache/2.2.15 (Red Hat)
    9 TxHeader     c Last-Modified: Tue, 04 Mar 2014 05:08:34 GMT
    9 TxHeader     c ETag: "40085-5-4f3c0e55fb165"
    9 TxHeader     c Content-Type: text/html; charset=UTF-8
    9 TxHeader     c Accept-Ranges: bytes
    9 TxHeader     c Date: Sun, 23 Mar 2014 09:09:33 GMT
    9 TxHeader     c X-Varnish: 19241885 19241876
    9 TxHeader     c Age: 9
    9 TxHeader     c Via: 1.1 varnish
    9 TxHeader     c Connection: keep-alive
    9 Length       c 0
    9 ReqEnd       c 19241885 1395565773.935906887 1395565773.936139584 0.000288963 0.000075579 0.000157118


3. varnishstat

这个命令可以查看varnish的工作状态,缓存命中率等信息