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


Posted in PHP onJune 20, 2013

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
PHP 相关文章推荐
php中几种常见安全设置详解
Apr 06 PHP
使用openssl实现rsa非对称加密算法示例
Jan 24 PHP
Yii框架中memcache用法实例
Dec 03 PHP
php+mysql实现用户注册登陆的方法
Jan 03 PHP
通过php修改xml文档内容的方法
Jan 23 PHP
PHP的引用详解
Feb 22 PHP
php自动载入类用法实例分析
Jun 24 PHP
php 生成Tab键或逗号分隔的CSV
Sep 24 PHP
PHP编程实现微信企业向用户付款的方法示例
Jul 26 PHP
php检查函数必传参数是否存在的实例详解
Aug 28 PHP
PHP常用日期加减计算方法实例小结
Jul 31 PHP
PHP实现一个轻量级容器的方法
Jan 28 PHP
解析PHP中常见的mongodb查询操作
Jun 20 #PHP
PHP 解决session死锁的方法
Jun 20 #PHP
解析PHP可变函数的经典用法
Jun 20 #PHP
使用PHP求两个文件的相对路径
Jun 20 #PHP
基于PHP服务端图片生成缩略图的方法详解
Jun 20 #PHP
解析thinkphp中的导入文件标签
Jun 20 #PHP
解析thinkphp import 文件内容变量失效的问题
Jun 20 #PHP
You might like
php生成二维码图片方法汇总
2016/12/17 PHP
获取焦点时,利用js定时器设定时间执行动作
2010/04/02 Javascript
javascript一个无懈可击的实例化XMLHttpRequest的方法
2010/10/13 Javascript
JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(六)
2012/04/07 Javascript
js截取字符串的两种方法及区别详解
2013/11/05 Javascript
解析URI与URL之间的区别与联系
2013/11/22 Javascript
jQuery实现设置、移除文本框默认值功能
2015/01/13 Javascript
jQuery动态星级评分效果实现方法
2015/08/06 Javascript
nodejs实现bigpipe异步加载页面方案
2016/01/26 NodeJs
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
2016/06/21 Javascript
vue使用原生js实现滚动页面跟踪导航高亮的示例代码
2018/10/25 Javascript
jQuery对底部导航进行跳转并高亮显示的实例代码
2019/04/23 jQuery
微信小程序之数据绑定原理解析
2019/08/14 Javascript
加速vue组件渲染之性能优化
2020/04/09 Javascript
详解JavaScript中new操作符的解析和实现
2020/09/04 Javascript
[01:29]2014DOTA2展望TI 剑指西雅图DK战队专访
2014/06/30 DOTA
python处理数据,存进hive表的方法
2018/07/04 Python
编写多线程Python服务器 最适合基础
2018/09/14 Python
Python实现的远程文件自动打包并下载功能示例
2019/07/12 Python
用python写一个定时提醒程序的实现代码
2019/07/22 Python
Django CBV与FBV原理及实例详解
2019/08/12 Python
pyMySQL SQL语句传参问题,单个参数或多个参数说明
2020/06/06 Python
安装并免费使用Pycharm专业版(学生/教师)
2020/09/24 Python
自定义Django_rest_framework_jwt登陆错误返回的解决
2020/10/18 Python
加拿大在线隐形眼镜专家:PerfectLens.ca
2016/11/19 全球购物
领先的荷兰线上超市:荷兰之家Holland at Home(支持中文)
2021/01/21 全球购物
财务人员个人自荐信范文
2013/09/26 职场文书
师范应届生语文教师求职信
2013/10/29 职场文书
工程承诺书怎么写
2014/05/24 职场文书
高中学生会竞选演讲稿
2014/08/25 职场文书
大学生学习面向未来的赶考思想汇报
2014/09/12 职场文书
公证委托书格式
2014/09/13 职场文书
2015年电话客服工作总结
2015/05/18 职场文书
小学教师见习总结
2015/06/23 职场文书
导游词之无锡梅园
2019/11/28 职场文书
Python 数据结构之十大经典排序算法一文通关
2021/10/16 Python