Varnish3.0.3完全安装手册


Varnish2.0以上的版本需要pcre库的支持,pcre库的作用是兼容正则表达式。

#wget http://sourceforge.net/projects/pcre/files/pcre/8.31/pcre-8.31.tar.gz/download

#tar –zxvf pcre-8.31.tar.gz

#cd pcre-8.31

#./configure –prefix=/usr/local/pcre

#make&&make intall


Varnish3 需要的依赖包

automake

autoconf

libtool

ncurses-devel 如果没有这个包bin目录下就没有varnishstat、varnishtop、varnishhit三个程序

libxslt

groff

pcre-devel

pkgconfig


下面是安装varnish,这里使用的是3.0.3的版本。

wget http://repo.varnish-cache.org/source/varnish-3.0.3.tar.gz

tar –zxvf varnish-3.0.3.tar.gz

cd varnish-3.0.3

export PKG_CONFIG_PATH=/usr/local/pcre/lib/pkgconfig

./configure --prefix=/data/program/varnish

make&&make install

mkdri –p /etc/varnish

uuidgen>/etc/varnish/secret &&chmod 0600 /etc/varnish/secret

生成验证文件,varnihs3需要验证启动

useradd -s /sbin/nologin varnish

mkdir /data/program/varnish/log

touch /data/program/varnish/log/varnish.log (为生成log用)

mkdir /data/program/varnish/cache(存放缓存文件的地方)

chown –R varnish:varnish/data/program/varnish


没有使用网上说的系统启动方式,自定义了一个启动脚本,优化参数一目了然

touch /data/program/varnish/bin/startvarnish.sh

#!/bin/bash

/data/program/varnish/sbin/varnishd \

-a 100.11.6.202:80 \ (指定varnish服务启动的地址及端口可以是0.0.0.0:port

-T 127.0.0.1:8000 \ (指定varnish的管理地址及端口)

-f /data/program/varnish/etc/varnish/default.vcl\ (指定varnish启动时调用的配置文件)

-u varnish -g varnish \ (启动varnish的用户及组)

-S /etc/varnish/secret \ (管理varnish的认证文件)

-t 120 \ (默认TTL

-s file,/data/program/varnish/cache/varnish_storage.data,18G \ (使用了ssnp内存映射的数据存储类型,此处的varnish_storage.data 文件不需创建,启动varnish会自动生成)或者使用如下一种数据存储类型 ||

-s malloc,18G (使用内存和虚拟内存,)

-p thread_pool_max=8000 \ (-p是一个优化参数,线程池可创建的最大线程)

-p thread_pools=8 \ (定义线程池个数,最好与逻辑cpu个数相同)

-p thread_pool_min=10 \ (varnish启动每个线程池生成多少个线程,启动是设的小些)

-p thread_pool_timeout=10 \ 表示thread的超时过期时间。当thread数大于thread_pool_min设定值时,如果thread空闲超过thread_pool_timeout设定的时间,thread就会被释放掉

-p lru_interval=259200 \

这是个时间参数,表示在内存中如果某一个对象超过了此参数设定的时间后还没有被重用时,就把这个对象从LRULeast Recently Used)队列中移除。这是缓存系统的一个常用算法。合理地设置这个时间,可以提高系统的运行效率,单位是秒

-p listen_depth=2048 这个参数用于设置TCP连接队列的长度,即若服务无法及时响应先将其存放在队列中等待,将其设置得大一些可以提高并发处理的能力

/data/program/varnish/bin/varnishncsa -nvarnishone -w /data/program/varnish/log/varnish.log &

这条是通过varnishncsa来将varnish的日志写到varnish.log里,varnishone是varnish运行过程中产生日志的一个内存空间,它是一个以主机名命名的文件夹,具体位置在/data/program/varnish/var/varnish下与你的主机名有关,是系统自动生成的所以上面的命令可以写成

/data/program/varnish/bin/varnishncsa -n /data/program/varnish/var/varnish/varnishone-w /data/program/varnish/log/varnish.log &

-n 读取内存空间

-w将日志写到的地方


下面是varnish的重头戏,varnish 配置文件:

# This is a basic VCL configuration file forvarnish. See the vcl(7)

# man page for details on VCL syntax andsemantics.

#

# Default backend definition. Set this to point to your content

# server.

定义后端服务器

backend server1 {

.host= "100.11.6.202";

.port= "8080";

}

backend server2 {

.host= "100.11.6.204";

.port= "8080";

}

定义调度器,调度方法为轮询,调度器名称为server

director server round-robin {

{ .backend = server1; }

{ .backend = server2; }

}

如果请求的服务器地址是100.11.6.202(也可以是域名)则调用server这个调度器

sub vcl_recv {

if(req.http.host ~ "100.11.6.202") {

set req.backend=server;

}

}


#定义acl,用于管理缓存,允许acl中定义的网段去管理varnish

acl purge {

"localhost";

"127.0.0.1";

"172.30.0.0"/16;

"10.100.6.0"/8;

}

# Below is a commented-out copy of thedefault VCL logic. If you

# redefine any of these subroutines, thebuilt-in logic will be

# appended to your code.

subvcl_recv {

if(req.restarts == 0) {

if (req.http.x-forwarded-for) {

set req.http.X-Forwarded-For =

req.http.X-Forwarded-For +", " + client.ip;

} else {

set req.http.X-Forwarded-For = client.ip;

}

}


压缩设置,图片不压缩

if(req.http.Accept-Encoding) {

if (req.url ~ ".(jpg|png|gif|jpeg|flv)$") {

remove req.http.Accept-Encoding;

remove req.http.Cookie;

} else if (req.http.Accept-Encoding ~ "gzip") {

set req.http.Accept-Encoding = "gzip";

} else if (req.http.Accept-Encoding ~ "deflate") {

set req.http.Accept-Encoding = "deflate";

} else {

remove req.http.Accept-Encoding;

}

}

不是get、head 、put、 post、 trace、 options、 delete 操作的返回pipe不缓存

if(req.request != "GET" &&

req.request != "HEAD" &&

req.request != "PUT" &&

req.request != "POST" &&

req.request != "TRACE" &&

req.request != "OPTIONS"&&

req.request != "DELETE") {

return(pipe);

}


if(req.request == "purge") {

if (!client.ip ~ purge) {

error 405 "Not allowed.";

}

return(lookup);

}

#缓存方法是GET及HEAD的请求

if(req.request != "GET" && req.request != "HEAD") {

return(pass);

}

#不缓存认证及cookie信息

# if (req.http.Authorization || req.http.Cookie) {

# /* Not cacheable by default */

# return (pass);

# }

#请求是GET且以jsp和do结尾或包含?的url直接访问后端服务器不缓存

# if (req.request =="GET"&&req.url~"(?i)\.(jsp|do)($|\?)") {

# return (pass);

# }

# return (lookup);


}


sub vcl_pipe {

# #Note that only the first request to the backend will have

# #X-Forwarded-For set. If you useX-Forwarded-For and want to

# #have it set for all requests, make sure to have:

# #set bereq.http.connection = "close";

# #here. It is not set by default as itmight break some broken web

# #applications, like IIS with NTLM authentication.

return (pipe);

}

#

subvcl_pass {

return (pass);

}

#

subvcl_hash {

hash_data(req.url);

if(req.http.host) {

hash_data(req.http.host);

}else {

hash_data(server.ip);

}

return (hash);

}

#

subvcl_hit {

return (deliver);

}

#

subvcl_miss {

return (fetch);

}

#

subvcl_fetch {

if(beresp.ttl <= 0s ||

beresp.http.Set-Cookie ||

beresp.http.Vary == "*") {

/*

* Mark as "Hit-For-Pass" for the next2 minutes

*/

set beresp.ttl = 120 s;

return (hit_for_pass);

}

#下为不缓存404的代码设置

if (beresp.status == 404){

set beresp.ttl = 0s;

return (hit_for_pass);

}

#以css、js、html、htm结尾的文件缓存5

# if (req.request == "GET" && req.url ~"\.(css|js|html|htm)$") {

# set beresp.do_gzip = true;

# set beresp.ttl = 300s;

# }

#图片缓存7

if(req.request == "GET" && req.url ~"\.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|img|bmp|wmf)$") {

set beresp.ttl = 7d;

}

return(deliver);

}

此函数用来统计请求是否在varnsih中命中

subvcl_deliver {

if(obj.hits > 0) {

setresp.http.X-Cache = "Hit from p_w_picpath.domain.com";

} else {

set resp.http.X-Cache = "Miss from p_w_picpath.domain.com";

}

return (deliver);

}

#

# sub vcl_error {

# set obj.http.Content-Type = "text/html; charset=utf-8";

# set obj.http.Retry-After = "5";

# synthetic {"

# <?xml version="1.0"encoding="utf-8"?>

# <!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Strict//EN"

# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

# <html>

# <head>

# <title>"} + obj.status + " " + obj.response +{"</title>

# </head>

# <body>

# <h1>Error "} + obj.status + " " + obj.response +{"</h1>

# <p>"} + obj.response + {"</p>

# <h3>Guru Meditation:</h3>

# <p>XID: "} + req.xid + {"</p>

# <hr>

# <p>Varnish cache server</p>

# </body>

# </html>

# "};

# return (deliver);

# }

#

subvcl_init {

return (ok);

}

#

subvcl_fini {

return (ok);

}

配置文件见的一些说明:

VCL使用说明
VCL
,即为VarnishConfiguation Language,用来定义varnish的存取策略,VCL语法比较简单,跟Cperl比较相似,可以使用指定运算符“=”,比较运算符“==”,逻辑运算符“!,&&,!!”等形式。还支持正则表达样和用“~”进行ACL匹配运算,同时还可以使用“set”这样的关键字来指定变量。
需要注意的是,“\”字符在VCL里没有特别的含义,这点与其它语言略有不同,另外,VCL只是配置,并不是真正的编程语言,没有循环,也没有自定义变量。
在讲述Varnish配置之前,首先需要了解下varnish的配置语法,即VCL,下面对VCL常用的

一些内置函数和公用变量进行详细介绍。


函数样式:其中(?i)是正则表达式中不区分大小写的意思。

sub vcl_recv {

if(req.http.host ~ "(?i)example.com") {

set req.backend = foo;

}elsif (req.http.host ~ "(?i)example.org") {

set req.backend = bar;

}

}

这段代码的含义如果请求的域名是example.com则调用foo来响应,如果请求的域名是example.org 则调用bar来响应,foo、bar可能是调度器或一个定义的后端服务器。这样就可以通过域名来做url跳转


Varnish的调度算法:

random 随机

client 相当于源地址散列算法

hash 基于url的一个哈希算法

round-robin 轮询

dns

fallback


varnish 检测后端服务是否健康的变量

.url 检测一个特定的文件

.request 检测一个完整的http协议请求

.window 开启检测polls的窗口,默认是 8

.threshold 每个窗口成功返回线程数,默认是3

.interval 检测的频度默认每秒5

.timeout 探针的过期时间

backend www {

.host = "www.example.com";

.port = "http";

.probe = {

.url = "/test.jpg";

.timeout= 0.3 s;

.window = 8;

.threshold = 3;

.initial = 3;

}

}


vcl_recv

用于接收和处理请求,当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求,此函数一般以如下几个关键字结束:

pass

pipe

lookup 表示在缓存里查找被请求的对象,并且根据查找的结果把控制权交给函数vcl_hit或者函数vcl_miss

error code [reason]


vcl_pipe

此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容返回给客户端,直到这个链接关闭,此函数一般以如下几个关键字结束:

pipe

error code [reason]


vcl_pass

此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,后端主机应答数据后送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容,此函数一般以如下几个关键字结束:

pass

restart

error code [reason]


vcl_hit

在执行lookup指令后,如果在缓存中找到请求的内容,将自动调用该函数,此函数一般以如下几个关键字结束:

deliver

pass

error code [reason]


vcl_miss

vcl_hash

vcl_fetch

vcl_deliver

vcl_error

vcl_fini

变量说明:

now 当前时间

.host 源主机名或后台服务器IP地址

.port 源服务名或者服务端口号。

client.ip 客户端IP

server.hostname varnish服务器主机名

server.identity varnish服务器标识

server.ip varnish服务器的IP

server.port varnish服务器的端口号

req.request 请求类型 get post head ……

req.url 请求的URL

req.proto client使用的HTTP协议版本

req.backend 提供这个请求的原服务器名

req.backend.healthy 提供这个请求的原服务是否正常提供服务

req.http.header 相应的HTTP的header

req.hash_always_miss 强迫varnish忽略这一请求,直接从元数据库取数据。

req.hash_ignore_busy 在cache lookup时,忽略忙的对象。

req.can_gzip 客户端是否接受gzip编码


直接向后端服务请求时使用的变量:

bereq.request 请求类型 head get post……

bereq.url

bereq.proto

bereq.http.header

bereq.connect_timeout 等待连接源数据库的时间(以秒计算)

bereq.first_byte_timeout 连接后,得到第一个字节的时间(以秒计算)

bereq.between_bytes_timeout 在两个字节之间的时间(以秒计算)


从后端服务获取数据,在写入cache之前使用的变量,也就是说:在vcl_fetch中使用的变量:

beresp.do_esi 解析ESI对象

beresp.do_gzip 存储前是否压缩

beresp.do_gunzip 存储前是否解压缩

beresp.proto 源数据库使用的HTTP协议。

beresp.status 由varnish返回的HTTP状态码

beresp.response 由varnish返回的HTTPstatus信息

beresp.ttl 目标在cache中存活时间


从cahce器获取内容后,下面的变量可以使用,也就是说在 vcl_hit and vcl_deliver.函数中使用的变量:


obj.proto 对象检索时使用的http协议。

obj.status 由varnish服务器返回的http协议状态码。

obj.response由varnish服务器返回的http协议状信息。

obj.ttl 对象还能存活的时间。

obj.lastuse 对象上次访问的大致时间

obj.hits 对象被访问的大致次数,如果是0,表示对象已经从cache中丢失。


下面的变量在确定一个对象的hash值的时候可用。

req.hash 指定对象的hash key 在读和写的时候会被访问。


对客户端应答是使用的变量:

resp.proto response给客户端的HTTP 协议版本

resp.status 将被返回的HTTP协议状态码

resp.response将被返回的HTTP协议状态信息

resp.http.header 相应的HTTP header


varnishstat 的输出及说明

131500631.jpg

Client connections accepted (每秒)
Client requests received:经验表明connection:request=1:10左右比较理想,比这个数大很多或者小很多都是不好的
Backend connections failures:这个数应该尽可能小,没有最好,多的话就要看看backend指向的服务是否有问题了

N struct object:当前被cache的条目

N worker threads:当前工作线程数

N worker threads created:创建了多少线程(should be close to the number you are running now)

N worker threads not created :最好是0,表示varnish尝试创建线程但失败(由thread_pool_max的限制或线程池创建线程缓慢)

N worker threads limited :由于线程上限限制或者线程池反应延迟导致不能成功创建的线程数,越小越好

N overflowed work requests :进入等待队列的请求数,越小越好

N dropped work requests:队列被塞满后扔掉的请求,这个最好不要有

N LRU nuked objects:由于cache空间满而不得不扔掉的cache条目,如果这个数字是0,就没必要增加cache的大小了

Cache hits: 代表在这些请求中,反向代理服务器在缓存区中查找并且命中缓存的次数

Cache misses: 代表在这些请求中,反向代理服务器在缓存区中查找但是没有命中缓存的次数

N expired objects: 代表过期的缓存内容个数

N LRU moved objects: 代表被淘汰的缓存内容个数(最近最少使用算法)

Total header bytes: 代表缓存区中所有缓存过内容的HTTP头信息长度

Total body bytes: 代表缓存区中所有缓存过内容的正文长度


varnish 缓存管理

varnishadmin –S /etc/varnish/secret –T 127.0.0.1:8000

输入:help

124408912.jpg

Status 查看varnish的状态

Vcl.load <configname>是自己命名的一个文件,<filename>是实际存在的文件,若修改完配置文件想重新加载,可以这样:

Vcl.load newconfig /data/program/varnish/etc/varnish/default.vcl此为载入修改后的文件

Vcl.use newconfig 此为引用载入的文件

Vcl.discard 用来清除载入的文件(有时你会载入多个配置文件)

Vcl.list 可以查看你载入的配置文件

Vcl.show 查看当前使用的配置文件的内容

ban.url 用来清除缓存中的url 可以用正则,很常用

param.show [-l] 查看参数的意义

param.set <param> <value> 设置参数的值

storage.list 列出varnish缓存数据使用的文件类型


Varnish的一个显著优点是可以灵活的管理缓存内容,而管理缓存主要的工作是如何迅速有效的控制和清除指定的缓存内容,varnish清除缓存相对比较复杂,不过幸运的是,可以通过varnish的管理端口发送PURGE指令来清除不需要的缓存。
下面列出了清除缓存内容的命令格式:
ban.url <regexp>
下面的命令可以列出最近清除的详细URL列表:
ban.list
举例如下:
1、如果要清除http://www.example.com/a/2010.html的URL地址,可以执行如下命令:
varnishadm -T 127.0.0.1:8000 -S /etc/varnish/security ban.url /a/2010.html

2、批量清除类似http://www.example.com/a/b/s*.html的URL地址,可执行如下命令:
varnishadm -T 127.0.0.1:8000 -S /etc/varnish/security ban.url ^/a/b/s.*$
3、批量清除类似http://www.example.com/a/b/*.html的URL地址,可执行如下命令:
varnishadm -T 127.0.0.1:8000 -S /etc/varnish/security ban.url ^/a/b.*$
4、如果要清除所有缓存,可执行如下命令:
varnishadm -T 192.168.12.246:3500 purge.url ^.*$
5、查看最近清除的详细URL列表
[root@varnish-server ~]# varnishadm -T 127.0.0.1:8000 -S /etc/varnish/security

ban.list