解析Linux下Varnish缓存的配置优化

  Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。

  但与老牌的squid相比,各有各的优劣势,网上大量的相对比较只是在其个人对自己熟悉的应用的最大使用上的发挥而已,可能squid到了有能力的人手上才足以发挥最强大的威力

  Varnish采用了“Visual Page Cache”技术,在内存的利用上,Varnish比Squid具有优势,它避免了Squid频繁在内存、磁盘中交换文件,性能要比Squid高。

  通过Varnish管理端口,可以使用正则表达式快速、批量地清除部分缓存,这一点是Squid不能具备的。

  本人就varnish的一些见解与配置方法做简单的介绍与笔记

  实验环境:Red Hat Enterprise Linux Server release 5.4 (Tikanga)

  内核2.6.18-164.el5

  yum install pcre-devel     ##预先安装一个软件包,不然会提示错误

  tar zxvf varnish-2.1.3.tar.gz

  cd varnish-2.1.3

  ./configure --prefix=/usr/local/varnish-2.1.3

  make && make install

  编辑配置文件,有模版,但太多注释,最好自己新建一个

  vim /usr/local/varnish-2.1.3/etc/varnish/varnish.conf

  ############下面附上配置文件的内容及注释#######################

  #http请求处理过程

  #1,receive请求入口状态,根据vcl判断pass还是lookup本地查询

  #lookup,在hash表中查找数据,若找到则进入hit状态,否则进入fetch状态

  #pass,选择后台,进入fetch状态

  #fetch,对请求进行后端的获取,发送请求,获得数据,并进行本地存储

  #deliver,将数据发送给客户端,进入done

  #done,处理结束

  ##########配置后端服务器##############

  

复制代码 代码如下:

  backend linuxidc01 {

  .host = "192.168.1.142";

  .port = "7070";

  .probe = {

  .timeout = 5s;

  .interval = 2s;

  .window = 10;

  .threshold = 8;

  }

  }

  backend linuxidc02 {

  .host = "192.168.1.141";

  .port = "7070";

  .probe = {

  .timeout = 5s;

  .interval = 2s;

  .window = 10;

  .threshold = 8;

  }

  }

  ##############配置后端服务器组,进行健康检测6秒,使用random方式设置权重########

  #########另一种方式round-robin则默认轮询机制####################

  

复制代码 代码如下:

  director linuxidc15474 random

  { .retries = 6;

  { .backend = linuxidc02;

  .weight = 2;

  }

  { .backend = linuxidc01;

  .weight = 2;

  }

  }

  ##########定义访问列表,允许下列地址清除varnish缓存#######################

  

复制代码 代码如下:

  acl local  {

  "localhost";

  "127.0.0.1";

  }

  ########从url判断针对哪类后面服务器及缓存配置############################

  

复制代码 代码如下:

  sub vcl_recv

  {

  if (req.http.host ~ "^linuxidc15474.vicp.net")  #匹配域名跳转后台服务器

  { set req.backend = linuxidc15474; }

  else { error 404 "Unknown HostName!"; }

  if (req.request == "PURGE")    #不允许非访问控制列表内的IP清除varnish缓存

  { if (!client.ip ~ local)

  {

  error 405 "Not Allowed.";

  return (lookup);

  }

  }

  #清除url中有jpg等文件的cookie

  if (req.request == "GET" && req.url ~ "\.(jpg|png|gif|swf|jpeg|ico)$")

  {

  unset req.http.cookie;

  }

  #判断req.http.X-Forwarded-For 如果前端有多重反向代理,这样可以获取客户端IP地址。

  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; }

  ##varnish实现图片的防盗链

  #        if (req.http.referer ~ "http://.*)

  #          {

  #             if ( !(req.http.referer ~ "http://.*vicp\.net" ||

  #                   req.http.referer ~ "http://.*linuxidc15474\.net" ) )

  #                 {

  #                   set req.http.host = "linuxidc15474.vicp.net";

  #                   set req.url = "/referer.jpg";

  #                 }

  #              return(lookup);

  #          }

  #         else {return(pass);}

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

  req.request != "HEAD" &&

  req.request != "PUT" &&

  req.request != "POST" &&

  req.request != "TRACE" &&

  req.request != "OPTIONS" &&

  req.request != "DELETE")

  { return (pipe); }

  #对非GET|HEAD请求的直接转发给后端服务器

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

  { return (pass); }

  ##对GET请求,且url里以.php和.php?结尾的,直接转发给后端服务器

  if (req.request == "GET" && req.url ~ "\.(php)($|\?)")

  { return (pass); }

  ##对请求中有验证及cookie,直接转发给后端服务器

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

  { return (pass);}

  {

  ##除以上的访问请求,从缓存中查找

  return (lookup);

  }

  ##指定的font目录不进行缓存

  if (req.url ~ "^/fonts/")

  { return (pass); }

  }

  sub vcl_pipe

  { return (pipe); }

  ##进入pass模式,请求被送往后端,后端返回数据给客户端,但不进入缓存处理

  sub vcl_pass

  { return (pass); }

  sub vcl_hash

  {

  set req.hash += req.url;

  if (req.http.host)

  { set req.hash += req.http.host; }

  else { set req.hash += server.ip; }

  return (hash);

  }

  ##在lookup后如果在cache中找到请求的缓存,一般以下面几个关键词结束

  sub vcl_hit

  {

  if (!obj.cacheable)

  { return (pass); }

  return (deliver);

  }

  ##lookup后没有找到缓存时调用,以下面几个关键词结束,及调用fetch参数重新测试是否加入缓存

  sub vcl_miss

  { return (fetch); }

  #让varnish服务器缓存的类型,从后端取得数据后调用

  sub vcl_fetch

  {    if (!beresp.cacheable)

  { return (pass); }

  if (beresp.http.Set-Cookie)

  { return (pass); }

  ##WEB服务器指明不缓存的内容,varnish服务器不缓存

  if (beresp.http.Pragma ~ "no-cache" || beresp.http.Cache-Control ~ "no-cache" || beresp.http.Cache-Control ~ "private")

  { return (pass); }

  ##对访问中get有包含jpg,png等格式的文件进行缓存,缓存时间为7天,s为秒

  if (req.request == "GET" && req.url ~ "\.(js|css|mp3|jpg|png|gif|swf|jpeg|ico)$")

  { set beresp.ttl = 7d; }

  ##对访问get中包含htm等静态页面,缓存300秒

  if (req.request == "GET" && req.url ~ "\/[0-9]\.htm$")

  { set beresp.ttl = 300s; }

  return (deliver);

  }

  ####添加在页面head头信息中查看缓存命中情况########

  sub vcl_deliver

  {

  set resp.http.x-hits = obj.hits ;

  if (obj.hits > 0)

  { set resp.http.X-Cache = "HIT cqtel-bbs"; }

  else { set resp.http.X-Cache = "MISS cqtel-bbs"; }

  }

  #########################以上为 varnish的配置文件##########################

  创建用户:

  groupadd www

  useradd www -g www

  创建 varnish_cache的缓存位置

  mkdir /data/varnish_cache

  启动varnish

  ulimit -SHn 8192   ####设置文件描述符,因为我的机子性能并不好,可以按照自己的配置去设置

  /usr/local/varnish-2.1.3/sbin/varnishd -u www -g www -f /usr/local/varnish-2.1.3/etc/varnish/varnish.conf -a 0.0.0.0:80 -s file,/data/varnish_cache/varnish_cache.data,100M -w 1024,8192,10 -t 3600 -T 127.0.0.1:3500

  ####-u 以什么用运行 -g 以什么组运行 -f varnish配置文件 -a 绑定IP和端口 -s varnish缓存文件位置与大小 -w 最小,最大线程和超时时间 -T varnish管理端口,主要用来清除缓存

  #结束varnishd进程

  pkill varnishd

  启动varnishncsa用来将Varnish访问日志写入日志文件:

  /usr/local/varnish-2.1.3/bin/varnishncsa -w /data/logs/varnish.log &

  每天0点运行,按天切割Varnish日志,生成一个压缩文件,同时删除上个月旧日志的脚本(/var/logs/cutlog.sh):

  vim /usr/local/varnish-2.1.3/etc/varnish/cut_varnish_log.sh

  写入以下脚本:

  #!/bin/sh

  # This file run at 00:00

  date=$(date -d "yesterday" +"%Y-%m-%d")

  pkill -9 varnishncsa

  mv /data/logs/varnish.log /data/logs/${date}.log

  /usr/local/varnish-2.1.3/bin/varnishncsa  -w /data/logs/varnish.log &

  mkdir -p /data/logs/varnish/

  gzip -c /data/logs/${date}.log > /data/logs/varnish/${date}.log.gz

  rm -f /data/logs/${date}.log

  rm -f /data/logs/varnish/$(date -d "-1 month" +"%Y-%m*").log.gz

  定时任务:

  crontab -e

  00 00 * * * /usr/local/varnish-2.1.3/etc/varnish/cut_varnish_log.sh

  优化Linux内核参数

  vi /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

  使配置生效

  /sbin/sysctl -p

  通过Varnish管理端口,使用正则表达式批量清除缓存

  清除所有缓存

  /usr/local/varnish-2.1.3/bin/varnishadm -T 127.0.0.1:3500 url.purge *$

  清除image目录下所有缓存

  /usr/local/varnish-2.1.3/bin/varnishadm -T 127.0.0.1:3500 url.purge /image/

  127.0.0.1:3500 为被清除缓存服务器地址 www.linuxidc.com 为被清除的域名 /static/image/tt.jsp 为被清除的url地址列表

  /usr/local/varnish-2.1.3/bin/varnishadm -T 127.0.0.1:3500 purge "req.http.host ~ www.linuxidc.com$ && req.url ~ /static/image/tt.jsp"

  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  一个清除Squid缓存的PHP函数

  

复制代码 代码如下:

  <?php

  function purge($ip, $url)

  {

  $errstr = '';

  $errno = '';

  $fp = fsockopen ($ip, 80, $errno, $errstr, 2);

  if (!$fp)

  {

  return false;

  }

  else

  {

  $out = "PURGE $url HTTP/1.1\r\n";

  $out .= "Host:blog.s135.com\r\n";

  $out .= "Connection: close\r\n\r\n";

  fputs ($fp, $out);

  $out = fgets($fp , 4096);

  fclose ($fp);

  return true;

  }

  }

  purge("192.168.0.4", "/index.php");

  ?>

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  配置开机自动启动Varnish

  vim /etc/rc.d/rc.local

  在末行写入以下内容:

  ulimit -SHn 8192

  /usr/local/varnish-2.1.3/sbin/varnishd -u www -g www -f /usr/local/varnish-2.1.3/etc/varnish/varnish.conf -a 0.0.0.0:80 -s file,/data/varnish_cache/varnish_cache.data,100M -w 1024,8192,10 -t 3600 -T 127.0.0.1:3500

  /usr/local/varnish-2.1.3/bin/varnishncsa -w /data/logs/varnish.log &

  查看Varnish服务器连接数与命中率:

  /usr/local/varnish-2.1.3/bin/varnishstat

  以上为varnish的状态,

  1675         0.00         0.06 Client requests received   为服务端接收的客户端请求次数

  179         0.00         0.01 Cache hits    为命中缓存,从缓存中取得数据返回给客户端的次数,即命中率

  11         0.00         0.00 Cache misses  为跳过pass缓存,从后端服务应用中取得数据返回给用户的次数

  用help看看可以使用哪些Varnish命令:

  /usr/local/varnish-2.1.3/bin/varnishadm -T 127.0.0.1:3500 help