首页 > 代码库 > 缓存服务器varnish实践篇

缓存服务器varnish实践篇

一、实验环境

服务器IP地址系统版本
varnish服务器172.16.8.1Centos6.5
web1服务器172.16.8.5:81Centos6.5
web2服务器172.16.8.5:82Centos6.5
img1服务器172.16.8.5:83Centos6.5
img2服务器172.16.8.5:84Centos6.5
php1服务器172.16.8.5:85Centos6.5
php2服务器172.16.8.5:86Centos6.5


二、安装varnish

1、下载地址:

varnish-libs-3.0.4-1.el6.x86_64.rpm

varnish-3.0.4-1.el6.x86_64.rpm

varnish-docs-3.0.4-1.el6.x86_64.rpm


2、安装varnish

[root@localhost ~]# rpm -ivh varnish-docs-3.0.4-1.el6.x86_64.rpm varnish-3.0.4-1.el6.x86_64.rpm varnish-libs-3.0.4-1.el6.x86_64.rpm


3、配置文件详解

# cat /etc/sysconfig/varnish
/////////////
# Configuration file for varnish
#
# /etc/init.d/varnish expects the variable $DAEMON_OPTS to be set from this
# shell script fragment.
#
# Maximum number of open files (for ulimit -n)
NFILES=131072 //打开最大文件数
# Locked shared memory (for ulimit -l)
# Default log size is 82MB + header
MEMLOCK=82000 //默认日志大小
# Maximum number of threads (for ulimit -u)
NPROCS="unlimited" //最大线程数
# Maximum size of corefile (for ulimit -c). Default in Fedora is 0
# DAEMON_COREFILE_LIMIT="unlimited" //最大内核打开的文件数
# Set this to 1 to make init script reload try to switch vcl without restart.
# To make this work, you need to set the following variables
# explicit: VARNISH_VCL_CONF, VARNISH_ADMIN_LISTEN_ADDRESS,
# VARNISH_ADMIN_LISTEN_PORT, VARNISH_SECRET_FILE, or in short,
# use Alternative 3, Advanced configuration, below
RELOAD_VCL=1 //是否自动加载VCL
# This file contains 4 alternatives, please use only one.
## Alternative 1, Minimal configuration, no VCL //方案1,最小配置,不方便
#
# Listen on port 6081, administration on localhost:6082, and forward to
# content server on localhost:8080. Use a fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 #       -T localhost:6082 #       -b localhost:8080 #       -u varnish -g varnish #       -s file,/var/lib/varnish/varnish_storage.bin,1G"
## Alternative 2, Configuration with VCL //方案2,配置组件
#
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request. Use a
# fixed-size cache file.
#
#DAEMON_OPTS="-a :6081 #       -T localhost:6082 #       -f /etc/varnish/default.vcl #       -u varnish -g varnish #       -S /etc/varnish/secret #       -s file,/var/lib/varnish/varnish_storage.bin,1G"
## Alternative 3, Advanced configuration //方案3,高级配置
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/etc/varnish/default.vcl //默认的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=6081 //服务监听端口
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 //管理IP
VARNISH_ADMIN_LISTEN_PORT=6082 //管理端口
#
# # Shared secret file for admin interface
VARNISH_SECRET_FILE=/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}" //默认存储在文件里,我们这里修改为malloc
#
# # Default TTL used when the backend does not specify one //默认TTL时使用的后端不指定一个
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}"
#
## Alternative 4, Do It Yourself. See varnishd(1) for more information. //方案4,设置你自己的配置。看到varnishd(1)更多的信息。
#
# DAEMON_OPTS=""


4、修改启动脚本

# vim /etc/sysconfig/varnish
VARNISH_LISTEN_PORT=8080 #这里设置的监听端口设置为8080
VARNISH_STORAGE="malloc,64M" 设置的缓存内存为64M


5、启动varnish

# service varnish start


6、查看端口

wKiom1Np-_uR8wlAAAGCYAkcuv8831.jpg


7、连接管理端口

[root@localhost ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082


三、varnish实例

新增vcl文件:

[root@localhost ~]# vim /etc/varnish/test.vcl
//添加如下内容:
backend web1 {              //添加后端服务器web1,地址为172.16.8.5,端口为81,probe表示健康状态检测
  .host = "172.16.8.5";  
  .port = "81";
  .probe = {
    .url = "/index.html";  //健康检查要检查的文件
    .interval = 1s;     //每隔1秒对此后端主机172.16.8.5:81探测一次
    .window = 3;       //最近3次的探测请求
    .threshold = 1;    //在最近3次的探测请求中至少有1次是成功的(响应码为200)就判定此后端主机为正常工作状态。
  }
}
backend web2 {           //定义后端服务器web2
  .host = "172.16.8.5";
  .port = "82";
  .probe = {
    .url = "/index.html";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
backend img1 {      //定义后端图片服务器img1
  .host = "172.16.8.5";
  .port = "83";
  .probe = {
    .url = "/car.jpg";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
backend img2 {      //定义后端图片服务器img2
  .host = "172.16.8.5";
  .port = "84";
  .probe = {
    .url = "/car.jpg";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
backend php1 {      //定义后端php服务器php1
    .host = "172.16.8.5";
    .port = "85";
    .probe = {
    .url = "/index.php";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
backend php2 {    //定义后端php服务器php2
    .host = "172.16.8.5";
    .port = "86";
    .probe = {
    .url = "/index.php";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
director webserver random {       //定义web集群,采用random调度
    { .backend = web1; .weight = 3; }
    { .backend = web2; .weight = 1; }
}
director imgserver random {      //定义img集群
    { .backend = img1; .weight = 3; }
    { .backend = img2; .weight = 1; }
}
director phpserver random {     //定义php集群
    { .backend = php1; .weight = 3; }
    { .backend = php2; .weight = 1; }
}
  sub vcl_recv {         
 if (req.request == "PURGE") {   //定义缓存修剪
  if (!client.ip ~ purgers) {
    error 405 "Method not allowed";
  }
  return (lookup);
  }
  if (req.url ~ "\.php$"){    //如果请求是以.php结尾的,则pass,不缓存,直接交给后端处理响应
   set req.backend = phpserver;
   return(pass);
   }
  if (req.url ~ "\.(html|css|js)$"){ //如果是以.html .css .js 结尾的则发往web集群
  set req.backend = webserver;
}
 if (req.url ~ "\.(jpg|jpeg|png|gif)$"){  //如果是以.jpg .jpeg .png .gif 结尾的则发往img集群
  set req.backend = imgserver;
}
}
sub vcl_fetch {         //根据响应的内容做出缓存决策
    if (req.request == "GET" && req.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") {
        set beresp.ttl = 3600s;    //缓存3600s
    }
}
acl purgers {     //可以修剪缓存的用户地址
  "127.0.0.1";
  "172.16.8.2";
}
sub vcl_hit {     //如果请求的缓存存在,则执行purge命令,清除缓存
  if (req.request == "PURGE") {
    purge;
    error 200 "Purged";   //返还200的error状态吗
  }
}
sub vcl_miss {   //如果请求的内容缓存不存在,则返还404错误
  if (req.request == "PURGE") {
    purge;                      
    error 404 "Not in cache";
  }
}
sub vcl_pass {
  if (req.request == "PURGE") {
    error 502 "PURGE on a passed object";
  }
}
sub vcl_deliver {     //修改vcl_deliver增一个响应头部
   if (obj.hits > 0) {
     set resp.http.X-Cache = "HIT from"+" "+server.ip;
}
else {
    set resp.http.X-Cache = "Miss via"+" "+server.ip;
}
}


简单说明下此vcl文件:

在此vcl文件中采用了健康状态检查,缓存修剪,集群等功能

1、Varnish 检测后端主机的健康状态

     Varnish可以检测后端主机的健康状态,在判定后端主机失效时能自动将其从可用后端主机列表中移除,而一旦其重新变得可用还可以自动将其设定为可用。为了避免误判,Varnish在探测后端主机的健康状态发生转变时(比如某次探测时某后端主机突然成为不可用状态),通常需要连续执行几次探测均为新状态才将其标记为转换后的状态。


.probe中的探测指令常用的有:
(1) .url:探测后端主机健康状态时请求的URL,默认为“/”;
(2) .request: 探测后端主机健康状态时所请求内容的详细格式,定义后,它会替换.url指定的探测方式;

(3) .window:设定在判定后端主机健康状态时基于最近多少次的探测进行,默认是8;
(4) .threshold:在.window中指定的次数中,至少有多少次是成功的才判定后端主机正健康运行;默认是3;
(5) .initial:Varnish启动时对后端主机至少需要多少次的成功探测,默认同.threshold;
(6) .expected_response:期望后端主机响应的状态码,默认为200;
(7) .interval:探测请求的发送周期,默认为5秒;
(8) .timeout:每次探测请求的过期时长,默认为2秒;


   因此,如上vcl文件web1中表示每隔1秒对此后端主机探测一次,请求的URL为http://172.16.8.5:81/index.html,在最近3次的探测请求中至少有1次是成功的(响应码为200)就判定此后端主机为正常工作状态。


2、Varnish 缓存修剪

1、缓存内容修剪

    提高缓存命中率的最有效途径之一是增加缓存对象的生存时间(TTL),但是这也可能会带来副作用,比如缓存的内容在到达为其指定的有效期之间已经失效。因此,手动检验缓存对象的有效性或者刷新缓存是缓存很有可能成为服务器管理员的日常工作之一,相应地,Varnish为完成这类的任务提供了三种途径:HTTP 修剪(HTTP purging)、禁用某类缓存对象(banning)和强制缓存未命令(forced cache misses)。


    这里需要特殊说明的是,Varnish 2中的purge()操作在Varnish 3中被替换为了ban()操作,而Varnish 3也使用了purge操作,但为其赋予了新的功能,且只能用于vcl_hit或vcl_miss中替换Varnish 2中常用的set obj.ttl=0s。


在具体执行某清理工作时,需要事先确定如下问题:
(1)仅需要检验一个特定的缓存对象,还是多个?
(2)目的是释放内存空间,还是仅替换缓存的内容?
(3)是不是需要很长时间才能完成内容替换?
(4)这类操作是个日常工作,还是仅此一次的特殊需求?


2、移除单个缓存对象

     purge用于清理缓存中的某特定对象及其变种(variants),因此,在有着明确要修剪的缓存对象时可以使用此种方式。HTTP协议的PURGE方法可以实现purge功能,不过,其仅能用于vcl_hit和vcl_miss中,它会释放内存工作并移除指定缓存对象的所有Vary:-变种,并等待下一个针对此内容的客户端请求到达时刷新此内容。另外,其一般要与return(restart)一起使用。


3、强制缓存未命中

     在vcl_recv中使用return(pass)能够强制到上游服务器取得请求的内容,但这也会导致无法将其缓存。使用purge会移除旧的缓存对象,但如果上游服务器宕机而无法取得新版本的内容时,此内容将无法再响应给客户端。使用req.has_always_miss=ture,可以让Varnish在缓存中搜寻相应的内容但却总是回应“未命中”,于是vcl_miss将后续地负责启动vcl_fetch从上游服务器取得新内容,并以新内容缓存覆盖旧内容。此时,如果上游服务器宕机或未响应,旧的内容将保持原状,并能够继续服务于那些未使用req.has_always_miss=true的客户端,直到其过期失效或由其它方法移除。


4、Banning

      ban()是一种从已缓存对象中过滤(filter)出某此特定的对象并将其移除的缓存内容刷新机制,不过,它并不阻止新的内容进入缓存或响应于请求。在Varnish中,ban的实现是指将一个ban添加至ban列表(ban-list)中,这可以通过命令行接口或VCL实现,它们的使用语法是相同的。ban本身就是一个或多个VCL风格的语句,它会在Varnish从缓存哈希(cache hash)中查找某缓存对象时对搜寻的对象进行比较测试,因此,一个ban语句就是类似匹配所有“以/downloads开头的URL”,或“响应首部中包含nginx的对象”。例如:

ban req.http.host == "test.com"&& req.url ~ "\.gif$"


     定义好的所有ban语句会生成一个ban列表(ban-list),新添加的ban语句会被放置在列表的首部。缓存中的所有对象在响应给客户端之前都会被ban列表检查至少一次,检查完成后将会为每个缓存创建一个指向与其匹配的ban语句的指针。Varnish在从缓存中获取对象时,总是会检查此缓存对象的指针是否指向了ban列表的首部。如果没有指向ban列表的首部,其将对使用所有的新添加的ban语句对此缓存对象进行测试,如果没有任何ban语句能够匹配,则更新ban列表。


我们这里采用的第2种方法来修剪缓存,只能通过172.16.8.2,和127.0.0.1这2个地址来删除缓存!


四、测试

  • 第一次访问172.16.8.1/index.html

wKioL1NqCrPxcfJPAAGFrIV7I3s703.jpg


  • 第2次访问172.16.8.1/index.html

wKiom1NqC4XQjKwLAAGaLPuSmo0510.jpg


  • 删除缓存

wKiom1NqC6bi-L9hAAHAfgymsCw515.jpg


  • 再次访问:

wKioL1NqDGyCh81AAAEvK08dLZU918.jpg


  • 访问php文件,看看缓不缓存

wKiom1NqEOfyxjuAAAI1fVkjLc8912.jpg

从图看出,无论怎么样访问都不会缓存php文件!


五、Varnish 日志

1.varnishlog 命令

wKioL1NqFACyFaEiAAk3hzDaPrU519.jpg


2、varnishstat命令

wKioL1NqFFTi72LaAASJ9E94Zu4388.jpg