Varnish3原理学习

    Varnish is a state of the art web accelerator. Its mission is to sit in front of a web server an cache the content. It makes your web site go fast.

    以上是官方对varnish的解释,varnish的具体作用就不解释,你如果打算看这篇文章的话应该是对varnish有点初步了解过了的,下面主要讲怎么使用varnish。varnish2和varnish3在配置语法上有一点差异。

varnish的工作流程:

Varnish3原理学习

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

   Accept线程:接受请求后,组织成session结构,看是否有空闲的工作线程,如果有,将请求给它,如果overflow过大,则放弃该请求,否则,将其挂在overflow上
   Work线程:从overflow队列上摘取请求(struct ses),进入状态处理过程,处理结束后,通过pipe通信,将struct ses发送给epoll线程
   Epoll线程:将一个请求处理称作一个session,在session周期内,处理完请求后,会交给epoll处理,若还没有过期,将socket放入epoll的事件中,事件发生时,也会将其放入到overflow中
   Expire线程:对于缓存的对象,根据过期时间,组织成二叉堆,该线程周期检查该堆的根,处理过期的文件


请求处理流程

   请求的是通过进入状态转换机进行分步处理,通过Varnish Configuration Language(VCL)进行定制,对于每种状态,都可以通过VCL进行配置。状态的基本转换如下图所示:

Varnish3原理学习

    receive ,请求处理的入口状态,根据vcl判断该请求是pass,还是进行lookup
    lookup,在hash表中查找数据,若找到则进入hit状态,否则进入fetch状态
    pass,选择后台,进入fetch状态
    fetch 对请求的数据通过后端进行获取,发送请求,获得数据,并进行本地的存储
    delive,将数据发送给客户端,然后进入done
    done,处理结束事宜,对于一些请求需要做重新处理则可能重新进行状态转换或交给Epoll

安装varnish

1 通过发行版自带的包安装

curl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add -
echo "deb http://repo.varnish-cache.org/debian/ squeeze varnish-3.0" >> /etc/apt/sources.list
apt-get update
apt-get install varnish
2 通过源码包安装

#预先安装相关依赖包
apt-get insyall automake autoconf libtool groff libxslt1.1 libpcre3 make \
        libpcre3-dev pkg-config 
#下载源码包
wget 'http://repo.varnish-cache.org/source/varnish-3.0.2.tar.gz'
#安装过程
tar zxvf varnish-3.0.2.tar.gz
cd varnish-3.0.2
sh autogen.sh 
sh configure
make
make check
make install

#完成后bin文件默认的安装路径和conf文件默认路径
bin:/usr/local/sbin
conf:/usr/local/etc/varnish
3 启动varnish

  /usr/local/sbin/varnishd -h 可以查看varnish启动需要指定的参数,例如:

varnishd -f /yourpath/default.vcl -s malloc,1G -T 127.0.0.1:2000 -a 0.0.0.0:8080
  -f  指定varnish使用那个配置文件
  -s  指定varnish把后端的内容存储在哪里,malloc表示使用内存存储,1G表示空间1G
  -T  varnish提供了一个命令行模式的管理接口,一般建议绑在内网地址或者回环地址上
  -a  希望varnish监听在哪个端口上
 更多的参数可以通过-h查看

  测试完毕后用pkill varnish停止varnish,使web服务监听在8080端口,然后使varnish监听在80端口,这样varnish可以作为web服务的前端缓存使用,再次启动varnish。

4 varnish相关工具介绍,varnish有一些工具可以查看varnish的运行状况。
 

  varnishtop 读取共享内存的日志并持续显示相关信息,可以有-I, -i, -X and -x参数
  varnishhist  读取共享内存,生成持续更新的柱状图,显示最后N个请求的处理情况,命中就是('|'),未命中就是('#')
  varnishsizes  类似varnishhist,显示你服务的对象有多大
  varnishstat  统计varnish运行的一些情况

5 varnish配置语言

  要使用varnish,则必须知道VCL是什么,VCL(Varnish Configuration Language),下面简单的讲解一下VCL

  varnish有一个很好的配置系统,大部分系统使用的配置指令是让你打开或者关闭某个选项,varnish使用domain specific language(VCL),在运行时候,varnish会把vcl配置转化为二进制代码。varnish配置文件被分成多个子程序,不同的子程序在不同的时间执行,因为这些代码的执行是线性的,如果直到整个过程执行完毕,你也没有在你的子程序中调用相关的action,varnish会执行内建的vcl代码(这些代码在配置文件中处于注释状态)。大部分的执行都需要vcl_recv和vcl_fetch两个子程序。

  vcl_recv:在请求到达的时候被调用,当完整的请求到达并解析后,才决定是否服务这个请求、怎样服务、使用哪一台后端提供服务等等。在vcl_recv中你可以修改请求,比如修改cookies、增加或者删除请求头等等,不过要注意:在vcl_recv中只有一个请求对象可用,req对象是可用的。

  vcl_fetch:只有在文档被成功的从后端再次取回后调用,一般会在这一步修改返回头信息,在vcl_fetch中仍然有一个请求对象可以用,req是可用的,通常它包含的是后端回复的响应,beresp包含从后端返回的HTTP头信息。

  actions:主要的action有以下动作pass、hit_for_pass、lookup、pipe、deliver,每个action的行为如下:

    pass:当一个请求返回pass,响应子程序会把该请求传递到后端服务器,该结果不会被缓存,pass可以用到vcl_recv

    hit_for_pass:和pass很像,hit_for_pass会在cache中创建一个hitforpass对象,它的副作用是决定不cache内容,她允许没有缓存的请求传递至后端服务器,The same logic is not necessary in vcl_recv because this happens before any potential queueing for an object takes place。

    lookup:当你从vcal_recv中返回lookup时,是告诉varnish在缓存中寻找数据,如果没有相关数据,则运行pass,不能在vcl_fetch中返回lookup

    pipe:pipe可以在vcl_recv中被返回,pipe是一个短路客户端和后端服务器连接,

    deliver:给客户端返回被缓存的数据,通常在vcl_fetch中返回。

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

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

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

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

  vcl支持下列运算符:

    =  赋值
    ==  比较
    ~  匹配
    !  否定
    && 逻辑与
    ||  逻辑或
 

6 VCL语法简介

  vcl的语法非常简单,有点像C和perl,通过花括号分割代码块,语句以分号结束,vcl除了支持类似C语言的=、==、!=、&&、||等操作符,还支持正则表达式匹配~、!~操作符。基本字符串包含在“ ”之间,中间不能包含新行。长字符串包含在{“...”}之间,可以包含任何字符串,包括新行、其他控制字符等。在vcl中反斜杠没有特殊意义,因此可以在正则表达式中放心使用,而不用再次转义。字符串连接可以通过”+“操作符连接。

  set关键字:vcl中没有用户自定义变量,值只能赋给属于backend、request、objects的变量,大多数变量都是有类型的,你可以使用set关键字改变HTTP头信息,可以使用remove或者unset删除http头信息,可以使用rollback关键字回滚任何在req中的改变。还有synthetic、panic关键字等。

  return(action)关键字终止子程序,action依赖于deliver、error、fetch、hash、ok、pass、pipe、hit_for_pass、lookup、restart。

  vcl有if测试语句,但没有loops语句,include关键字可以把另一个vcl文件插入一个vcl文件的任意位置。

Backend declarations

   后端的声明和初始化可以通过在backend对象后面跟一个名称来声明,声明好的后端可以在稍后使用,为了避免后端服务器过载,可以使用.max_connections来设置后端的最大并发数,timeout参数是.connect_timeout等待的时间,.first_byte_timeout是收到后端返回的第一个字节所等待的时间,.host参数设置后端地址,.port设置后端监听的端口。

backend www {
  .host = "www.example.com";
  .port = "http";
  .connect_timeout = 1s;
  .first_byte_timeout = 5s;
  .between_bytes_timeout = 2s;
}

Directors

    directors是一个由后端服务器集群组成的逻辑组,directors最基本的功能是:假如一台使用中的后端宕机后,让varnish选择由那个后端服务器继续提供服务。有多种不同的director类型可供选择,不同的director使用不同的选择算法。

The family of random directors

    有三个random director使用相同的逻辑,分别是random director, client director,hash director。每个后端需要设置一个.weight选项,该选项设置每台后端获取流量的比例,低weight的获取流量就少。.retries默认值是该director含有的后端个数,如果第一次检测失败,director会尝试retries次,用来寻找后端集群中可用的后端

     random director:使用一个随机数种子选择后端

     client director:基于客户端的identity选择后端,可以设置vcl变量client.identity来鉴定客户端

     hash director:基于URL的hash值来选择后端

director b2 random {
  .retries = 5;
  {
    // We can refer to named backends
    .backend = b1;
    .weight  = 7;
  }
  {
    // Or define them inline
    .backend  = {
      .host = "fs2";
    }
  .weight         = 3;
  }
}

The round-robin director

    round-robin不需要设置任何参数,它会把第一个请求传递到第一台后端,把第二个请求传递到第二个后端。如果一个后端无法提供服务,varnish会尝试轮训完所有后端后才放弃该请求。

The DNS director

    dns director选择后端可以使用两种不同的方式,类似random director或者round-robin director,或者使用.list

director directorname dns {
        .list = {
                .host_header = "www.example.com";
                .port = "80";
                .connect_timeout = 0.4s;
                "192.168.15.0"/24;
                "192.168.16.128"/25;
        }
        .ttl = 5m;
        .suffix = "internal.example.net";
}
    在.list语句中,选项必须在IP列表之前,.list不支持IPV6,它不是一个白名单,而是一个实际的后端列表,.ttl指定了在dns lookup中 cache的持续时间 ,目前还不支持健康检测。

The fallback director

    fallback director选择第一台健康的后端提供服务,该director没有任何选项,如果第一台健康的后端失效后,会选择下一个健康的后端。

director b3 fallback {
  { .backend = www1; }
  { .backend = www2; } // will only be used if www1 is unhealthy.
  { .backend = www3; } // will only be used if both www1 and www2
                       // are unhealthy.
}
Backend probes

    后端探测,前面定义并初始化了后端,而后端探测可以让你确认后端是否正常服务,返回的状态可以通过req.backend.healthy来检测。probes有以下参数可供使用:

    url:指定一个从后端请求的url,默认是“/”
    request:从后端请求一个全路径的url,request会自动在所有的字符串后面添加\r\n,request的优先级比url要高
    window:经过多少次检查后我们确定后端是正常的,默认是8
    threshold:在window中多少次检测是成功的才认为后端是正常的,默认是3
    initial:在varnish启动时启动多少探针,默认和threshold一样。
    expected_response:期望后端返回的http状态码,默认200
    interval:多久检测一次后端,默认是每间隔5秒
    timeout:每次检测的超时时间,默认是2秒

backend www {
  .host = "www.example.com";
  .port = "http";
  .probe = {
    .url = "/test.jpg";
    .timeout = 0.3 s;
    .window = 8;
    .threshold = 3;
    .initial = 3;
  }
}
或者把probe分离出来

probe healthcheck {
   .url = "/status.cgi";
   .interval = 60s;
   .timeout = 0.3 s;
   .window = 8;
   .threshold = 3;
   .initial = 3;
   .expected_response = 200;
}

backend www {
  .host = "www.example.com";
  .port = "http";
  .probe = healthcheck;
}  

ACL

    acl声明并创建一个访问控制列表,在后面可以用来匹配客户端ip地址,如果acl指定一个主机名,但是varnish不能解析,acl会匹配匹配到的所有地址。如果地址前面加上!符号,表示拒绝掉匹配的地址。
acl local {
  "localhost";         // myself
  "192.0.2.0"/24;      // and everyone on the local network
  ! "192.0.2.23";      // except for the dialin router
}
if (client.ip ~ local) {
  return (pipe);
}

Functions

    支持的内建函数如下:

    hash_data(str)
    regsub(str, regex, sub)
    regsuball(str, regex, sub)
    ban(ban expression)
    ban_url(regex)


Subroutines

    子程序用在代码块,提高重用性和易读性,子程序在vcl中不需要配置参数,也没有返回值,在调用子程序时,使用call关键字后面跟子程序名即可。有一些特定的子函数挂载在varnish的工作队列上,这些子程序可以检查、操纵每个请求中HTTP头信息和变量,并在一定程度上决定怎样处理请求。

    vcl_init:在vcl加载的时候调用,在任何请求通过之前加载。
    vcl_recv:之前讲过,vcl_recv子程序可以被调用return()包含如下参数终止,error code、pass、pipe、lookup
    vcl_pipe:调用进入pipe模式,请求被传递到后端服务器,任何从客户端还是后端过来的数据都会原封不动的传递直到关闭该连接,return() error code、pipe
    vcl_pass:调用进入pass模式,请求被传递到后端,后端把回复传递到客户端,return() error code、pass、restart
    vcl_hash:
    vcl_hit:如果在cache lookup中发现了请求的文档,则调用vcl_hit,return() deliver、error code、pass、restart
    vcl_miss:如果在cache lookup中没有发现请求的文档,则调用vcl_miss,他的目的是决定是否尝试再次到后端获取文档,return() error code、pass、fetch
    vcl_fetch:在成功的从后端获取文档后调用,return() deliver、error code、hit_for_pass、restart
    vcl_deliver:cache中的一个对象被传递到客户端后调用,return() deliver、error code、restart
    vcl_error:在命中一个error时调用,明确的或者含蓄的后端或者内部的错误。

Variables

    子程序虽然不含参数,但是可以通过变量获取必要的信息。

The following variables are always available:

    now 返回当前时间

The following variables are available in backend declarations:

    .host  后端服务器的ip地址或者主机名
    .port  后端服务的名称或者端口

The following variables are available while processing a request:

    client.ip  客户端ip
    client.identity  鉴定客户端,一般用在client directory 负载均衡中
    server.hostname  server的主机名
    server.ip  
    server.port  
    req.request  请求url的类型,如GET POST
    req.url  请求的url
    req.proto  请求客户端的http协议版本
    req.backend  使用那个后端为该请求提供服务
    req.backend.healthy  后端是否健康存活,需要设置probe
    req.http.header  相应的http头
    req.hash_always_miss  强制cache miss该请求,如果设置为true,varnish会忽视所有存在的对象,并且总是从后端获取
    req.hash_ignore_busy  在cache lookup中忽视任何busy object
    req.can_gzip  客户端是否接收压缩头
    req.restarts  
    req.esi
    req.esi_level
    req.grace
    req.xid

The following variables are available while preparing a backend request:

    bereq.request  请求类型 GET POST
    bereq.url  请求url
    bereq.proto  请求协议版本
    bereq.http.header  请求头信息
    bereq.connect_timeout  连接后端前等待多少秒
    bereq.first_byte_timeout
    bereq.between_bytes_timeout

The following variables are available after the requested object has been retrieved from the backend,In other words, they are available in vcl_fetch:

    beresp.do_stream
    beresp.do_esi
    beresp.do_gzip  在存储object之前gzip对象,默认是false
    beresp.do_gunzip  在存储object之前unzip对象,默认是false
    beresp.proto  后端使用那个版本的协议回复客户端
    beresp.status  后端返回的http状态码
    beresp.response  后端返回的http状态信息
    beresp.ttl  设置object的保存时间
    beresp.grace  设置grace模式
    beresp.saintmode  设置saint模式
    beresp.backend.name  后端响应的名称
    beresp.backend.ip  后端响应的ip
    beresp.backend.port  后端响应的端口
    beresp.storage

After the object is entered into the cache, the following (mostly read-only) variables are available,typically in vcl_hit

    obj.proto  重新取回对象时http的协议版本
    obj.status  返回的http状态码
    obj.response  返回的http状态消息
    obj.ttl  object保存的时间
    obj.lastuse  
    obj.hits
    obj.grace
    obj.http.header

The following variables are available while determining the hash key of an object:

    req.hash

The following variables are available while preparing a response to the client:

    resp.proto
    resp.status
    resp.response
    resp.http.header


参考:

https://www.varnish-cache.org/docs/3.0/tutorial/vcl.html
https://www.varnish-cache.org/docs/3.0/reference/vcl.html#varnish-configuration-language

你可能感兴趣的:(Varnish3)