varnish 简介

varnish   是一款高性能的开源的HTTP加速器,采用了“VisualPage Cache”技术,被安装在web应用程序前面,缓存web应用程序,并响应用户请求,varnish 让您的web应用程序运行的更快,并且varnish 具有更加灵活,效率更高,资源占用的更少等优点。

varinish 特点

  1 是基于内存缓存,重启数据将消失

  2 利用虚拟内存方式,IO性能好

  3  VCL 配置管理比较灵活

  4  32 为系统上缓存文件大小为2G

  5  具有更强大的管理功能,

  6  具有强大的管理功能,例如varnishtop,varnishstat,varnishadmin

  7  利用二交叉堆管理缓存文件,达到积极删除目的

varnish的storage 方式可分为两种:

    1  malloc  通过malloc 获取内存

2  mmap file 创建大文件,通过二分法分段映射成1G以内的大块。

varnish 进程的工作模式:

    varnish 启动或者有2个进程master(managemment)进程和child(worker)进程。master 读入存储配置命令,进行初始化,然后fork,监控child。child则分配线程进行cache工作,child还会做管理线程和生成很多worker线程。


child 进程主线程初始化过程中,将存储大文件整个加载到内存中,如果该文件中超出系统的虚拟内存,则会减少原来配置mmap 大小,然后继续加载,这个时候创建并初始化空闲存储结构体,放在存储管理的struct中,等待分配

接着varnish某个负责接口新http连接开始等待用户,如果有新的http连接,但是这个线程只负责接收,然后幻想等待线程池中的work线程,进行请求处理。

  worker线程读入uri后,将会查找已有的object,命中直接返回,没有命中,则会从后端服务器中取出来,放到缓存中。如果缓存已满,会更加LRU算法,释放旧的object。对于释放缓存,有一个超时线程会检测缓存中所有的object的生命周期,如果缓存过期(ttl),则会删除,是否相应的存储内存。

varnish工作流程:

主进程fork 子进程,主进程等待子进程的信号,子进程退出后,主进程重新启动子进程,子进程生成若干线程

  Accept线程:接收请求后,组织成session结构,看是否空闲的工作线程,如果有,将请求给它,如果overflow 过大,则放弃该请求,否则,将其挂在overflow

  Work线程:从overflow队列上摘取请求(structses),进入状态处理过程,处理结束后,通过pipe通信,将struct ses 发送给epoll线程

  Epoll 线程:将一个请求处理称作一个session,在session 周期内,处理完请求后,会交给epoll处理,若还没有过期,将socket放入epoll的事件中,事件发生时,也会将其放入overflow

  Expire线程:对于缓存的对象,根据过期时间,组织成二交叉堆,该线程周期检查该堆的根,处理过期的文件。


二 varnish  内置函数


   1 vcl_recv 函数

     用于接收和处理请求。当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求。例如如何响应,怎么响应,使用那个后端服务器等

此函数一般以如下几个关键字结束。

     pass: 表示进入pass模式,把请求控制权交给vcl_pass函数

     pipe:表示进入pipe模式,把请求控制权交个vcl_pipe函数

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

    error code [reason]: 表示返回“code”给客户端,并放弃处理请求。“code”是错误标识,例如200 和405 等。“reason是错误提示信息


2 vcl_pipe 函数

  此函数在进入pipe 模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容返回给客户端,知道这个连接被关闭。

此函数一般以如下几个关键字结束

  error code [reason]

  pass

  restart 重新启动流程,增加启动次数,如果重新启动次数高于max_restart 发出一个错误警告

3 vcl_hash

  当您想把一个数据添加到hash 上时,调用此函数

4 vcl_hit

  在执行lookup 指令后,在缓存中找到请求的内容后将自动调用该函数。

  此函数一般以如下几个关键字结束。

  deliver:表示将找到的内容发送个客户端,并把控制权交给函数vcl_deliver

  error code [reason]

  pass

  restart 重启启动流程,增加启动次数,如果重新启动次数高于max_restart 发出一个错误警告

 5  vcl_miss 函数

 在执行lookup 指令后,在缓存中没哟找到请求的内容时自动调用该方法。此函数可用于判断是否需要冲后端服务器获取内容,此函数一般以如下几个关键字结束

fetch表示从后端获取请求的内容,并把控制权交给vcl_fetch函数

error code [reason]

pass

 6 vcl_fetch函数

    在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。

如此函数一般以如下几个关键字结束

     error code [reason]

     pass

     deliver

     esi

     restart 重新启动流程,增加启动次数,如果重新启动次数高于max_restart ,发出一个错误警告

 7  vcl_deliver 函数

     将在缓存中找到请求的内容发送给客户端前调用此方法

     此函数一般以如下几个关键字结束

     error code [reason]

 deliver

 restart 重新启动流程,增加启动次数,如果重新启动次数高于max_restarts 发出一个错误警告


8  vcl_error

   出现错误时调用此函数。

   此函数一般以如下几个关键字结束

    deliver

    restart

在vcl 中有个三个重要的数据结构:request,response,object

     request: 数据从客户端进来,对应req对象,当varnish 收到一个请求的时候就会创建req对象,在vcl_recv中的大部分工作都是在req对象展开的

     response数据从后端服务器过来,对应beresp 对象,它包含从后端服务器传递过来数据的头信息,在vcl_fetch 中的大部分工作都是在beresp 对象展开的。

     object存储在cache 中的数据,对于obj对象,大多数只读的对象存贮在内粗中,只有obj.ttl是可写的,其余都是只读的

  vcl 支持下列运算符

      = 赋值

      == 比较

      ~ 匹配

      ! 否定

      &&逻辑与

      || 逻辑或


 varnish 请求处理流程


详细的处理过程



 varnish 内置公用变量

1   VCL 内置的公用变量可以用在不同的VCL 函数中,根据这些公用变量使用不同阶段,下面依次介绍当请求到达后,可以使用的公用变量如下所示

req.backend  指定对应的后端主机

server.ip         表示服务器端IP

client.ip          表示客户端IP

req.request       指定请求类型,例如GET,HEAD,POST

req.url           指定请求的地址

req.proto         表示客户端发起请求的HTTP协议版本

req.http.header    表示请求中http头部信息

req.restarts        表示请求重启的次数,默认最大值为4

req.grace         表示,当一个请求命中了一个刚刚过期的object,由于回源需要一段时间,为了立刻返回,那么在过期后的req.grace时间内,可以将过期的那个object返回给客户端,当然,这要求beresp.grace >= req.grace

2  varnish在向后端主机请求时,可以使用的公用变量如下所示:

beresp.request  指定请求的类型,例如GET,HEAD

beresp.url      指定请求的地址

beresp.proto    表示客户端发起请求的http 协议版本

beresp.http.header 表示对应请求中http 头部信息

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

beresp.grace       表示一个object即使已经过期了,仍然在缓存中存放一段时间

beresp.saintmode  设置saint模式,Saint mode允许您抛弃一个后端服务器或者另一个尝试的后端服务器或者cache中服务陈旧的内容

 beresp.do_gzip      在存储object之前gzip对象,默认是false

3 cache 或者后端主机获取内容后,可以使用的公用变量如下所示

obj.status      表示返回内容的请求状态代码,例如200302504

obj.cacheable   表示返回的内容是否可以缓存,也就是说,如果HTTP返回时200.203300301302404410等,并且有非0的生存期,则可以缓存

 obj.valid 表示是否是有效的HTTP应答

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

 obj.proto  表示返回内容的HTTP协议版本

 obj.ttl 表示返回内容的生存周期,也就是缓存时间,单位是秒

 obj.lastuse 表示返回上一次请求到现在的时间间隔,单位是妙

4 对客户端应答时,可以使用的公用变量如下所示

   resp.status   表示返回给客户端的HTTP状态代码

   resp.proto    表示返回给客户端的HTTP协议版本

   resp.http.header 表示返回给客户端的HTTP协议版本

   resp.response    表示返回给客户端的HTTP 状态信息

   req.backend.healthy  后端是否健康存活,需要设置probe


 varnish 管理工具详解


  1 varnishd 指令

      -a address:port   表示varnishhttpd 的监听地址及端口

      -b address:port   表示后端服务器地址及端口

      -d 表示使用debug 调试模式

      -f file 指定varnish服务器的配置文件

      -p param=value  指定服务器的参数,用来优化varnish性能

      -P file varnish进程PID文件存放路径

      -n dir 指定varnish的工作目录

      -s kind[,storageoptions]指定varnish缓存内容的存放方式,常用的方式有:“-s file,<dir_or_file>,<size>”

其中”<dir_or_file>”指定缓存文件的存放路径,“<size>” 指定缓存文件的大小

        -t  指定缺省的TTL

        -T address:port 设定varnishtelnet 管理端口地址及其端口

        -w int[,int[,int]] 设定varnish的工作线程数,常用的方式有:

 -w min,max  

 -w min,max,timeout

        -V   显示版本号

        -u   指定运行的用户

  2 varnsihncsa  NCSA 的格式显示日志

     varnishncsa 工具读取共享内存的日志,然后以apache/NCSA的格式显示出来,下面的选项可以用

 -a   当把日志写到文件里时,使用附加,而不是覆盖

 -b   只显示varnishd和后端服务器的日志

 -C  匹配正则表达式的时候,忽略大小写差异

 -c  只显示varnishd和客户端的日志

 -D  以进程方式运行

 -d  在启动过程中处理旧的日志,一般情况下,varnishhist只会在进程写日志后启动

 -f  在日志输出中使用X-Forwarded-ForHTTP 头代替client.ip

 -l  regex 匹配正则表达式的日志,如果没有使用-i或者-I,那么所有的日志都会匹配

 -I  tag  匹配指定的tag,如果没有使用-I 或者-I,那么所有的日志都会被匹配

 -n  指定varnish实例的名字,用来获取日志,如果没有指定,默认使用主机名

 -P file  记录PID号的文件

 -r file 从一个文件读取日志,而不是从共享内存读取

 -w file 把日志写到一个文件里面代替现实他们,如果不是使用-a参数就会发生覆盖,如果varnishlog在写日志时,接收到一个SIGHUP信号,他会创建一个新的文件,老的文件可以移走

 -X regex 排除匹配正则表达式的日志

 -x tag 排除匹配tag的日志


 3 varnishlog 工具读取和显示共享内存的日志

-a   当把日志写到文件里时,使用附加,而不是覆盖。

-b   只显示varnishd和后端服务器的日志

-C    匹配正则表达式的时候,忽略大小写差异

-c    只显示varnishd和客户端的日志

-D    以进程的方式运行

-d    在启动过程中除了旧的日志,一般情况下,varnishhist只会在进程写入日志后启动

-I  regex 匹配正则表达式的日志,如果没有使用-i或者-I,那么所有的日志都会匹配。

-I tag  匹配指定的tag,如果没有使用-i或者-I,那么所有的日志都会被匹配。

-k num  只显示开始的num个日志记录

-n  指定varnish实例的名字,用来获取日志,如果没有指定,默认使用主机名

-O   以请求ID 给日志分组,这个功能没有多大用处。如果要写到一个文件里面使用-w 选项

-P  file记录PID号的文件

-r file 从一个文件读取日志,而不是从共享内存读取

-s    sum跳过开始的num条日志

-u     无缓冲的输出

-V  显示版本,然后退出

-w file 把日志写到一个文件里代替显示他们,如果不是用-a参数就会发生覆盖,如果varnishlog在写日志时,接收到一个SIGHUP信号,他会创建一个新的文件。老的文件可以移走。

-X regex  排除匹配正则表达式的日志

-x tag  排除匹配tag 的日志

如果-o  选项被指定,需要使用正则表达式和tag来制定需要的日志


 4 varnishreplay  

     varnishreplay 工具类似varnish logs 尝试将流量复制。下面的参数是可用的:

    -a  backend 发送到这台服务器的TCP 流量,指定一个地址和端口,这个选项只能被IPV4上支持

   -D 打开debug模式

   -r  file 使用文件里的语法分析日志,这个参数是强制的

5 varnishsizes

varnishsizes 工具读取varnishd(1)的共享内存日志,生成一个连续不断更新的柱状图显示最后N 个请求的分布。N 的值取决于左上角垂直刻度的高度。水平尺度私对数。如果命中,则是使用”|”表示,如果没有命中,使用“#”表示

可使用的参数

-b   分析指定后端服务器的日志,如果没有使用-b-c参数,varnish就充当他们

-C   忽略正则表达式的大小写

-c    分析指定客户端的日志

-d   在启动过程中处理旧的日志,一般情况下,varnishhist只会在进程写入日志后启动

-I regex  匹配正则表达式的日志,如果没有使用-I或者-I,那么所有的日子都会匹配

-I tag  匹配指定tag,如果没有使用-i或者-I,那么所有的日志都会被匹配。

-n   指定varnish实例的名字,用来获取日志,如果没有指定,默认使用主机名

-r file 读入日志文件,代替共享内存。

-V    显示版本号,然后退出。

-w delay 等待更新的延迟时间,默认是1

-X regex 排除匹配表达式的日志

-x tag   排斥匹配tag 的日志




 6 varnishstat 工具显示一个运行varnishd实例的相关统计数据。

可用的参数

-1  只显示一次就退出

-f   使用逗号分隔字段列表来显示,使用“^”开始排除列表

-l   监听有效的列使用-f 参数

-n   指定varnishd实例来对去日志,如果没有指定,则默认使用主机名

-V   显示版本号,然后退出

-W dealy 刷新时间间隔,默认1s

中心显示中每列的含义,从左到右:

  1

  2  从最后一秒更新以来的每秒的一个平均值,或者一个不能计算的周期

  3 从进程开始到现在每秒的平均值,或者是一个不能计算的周期

  4 描述

当使用-1选项,输入列的含义,从左到右:

  1 特征名字

  2  

  3  从进程开始到现在没秒的平均值,或者是一个不能计算的周期。

  4 描述


7  varnishtop 工具读取varnishd(1) 共享内存的日志,连续不断的更新和显示日志记录。使用-I-i-X-x 选项适当的过滤,它可以显示一个排序关于请求的内容,客户端,用户代理,或者其他记录在日志的信息。

可选用的参数

  -1  代替连续不断的更新和显示,只显示一次然后退出。。暗示:-d

  -b  包含指定后端服务器的日志,如果没有使用-b-c,那么varnishtop但当这两种角色。

  -C  使用正则表达式的时候忽略大小写

  -c  包含指定客户端的日志,如果没有使用-b-cvarnishtop但当这两种角色

  -d  启动的时候是使用旧的日志记录,一般那情况下,varnishtop只读取其他启动以后生产的日志。

  -f  只显示日志的第一列

  -I regex 匹配正则表达式的日志,如果没有使用-I 或者-i,那么所有的日志都会匹配。

  -I tag 匹配指定的tag,如果没有使用-i或者-I,那么所有的日志都会被匹配。

  -n    指定varnish实例的名字,用来获取日志,如果没有指定,默认使用主机名

  -r  file  读入日志文件,代替共享内存

  -V  显示版本号,然后退出

  -X regex 排除匹配表达式的日志

  -x tag  排除匹配tag 的日志


        参考http://www.cnblogs.com/derekchen/archive/2011/12/09/2282909.html