Linux之varnish

  一:varnish简介

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

    Varnish 的作者Poul-Henning Kamp是FreeBSD的内核开发者之一,他认为现在的计算机比起1975年已经复杂许多。在1975年时,储存媒介只有两种:内存与硬盘。但现在计算机系统的内存除了主存外,还包括了CPU内的L1、L2,甚至有L3快取。硬盘上也有自己的快取装置,因此Squid Cache自行处理物件替换的架构不可能得知这些情况而做到最佳化,但操作系统可以得知这些情况,所以这部份的工作应该交给操作系统处理,这就是 Varnish cache设计架构.

  二:varnish设计机构图




   


 三:VCL 处理流程

Varnish 处理 HTTP 请求的过程大致分为如下几个步骤。

    - Receive 状态(vcl_recv)。也就是请求处理的入口状态,根据 VCL 规则判断该请求应该 pass(vcl_pass)或是 pipe(vcl_pipe),还是进入 lookup(本地查询)。

    - Lookup 状态。进入该状态后,会在 hash 表中查找数据,若找到,则进入 hit(vcl_hit)状态,否则进入 miss(vcl_miss)状态。

    - Pass(vcl_pass)状态。在此状态下,会直接进入后端请求,即进入 fetch(vcl_fetch)状态

    - Fetch(vcl_fetch)状态。在 fetch 状态下,对请求进行后端获取,发送请求,获得数据,并根据设置进行本地存储。

    - Deliver(vcl_deliver)状态。将获取到的数据发给客户端,然后完成本次请求

   

1) VCL 内置函数

 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”是错误提示信息.


 vcl_pipe 函数
   此函数在进入 pipe 模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容返回给客户端,直到这个连接被关闭。
此函数一般以如下几个关键字结束。
error code [reason]。
pipe


vcl_pass 函数

   此函数在进入 pass 模式时被调用,用于将请求直接传递至后端主机。后端主机在应答数据后将应答数据发送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容。

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

error code [reason]。

pass。

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


vcl_hash

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

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

vcl_hit 函数

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

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

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

error code [reason] 。

pass。

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


  vcl_miss 函数

  在执行 lookup 指令后,在缓存中没有找到请求的内容时自动调用该方法。此函数可用于判断是否需要从后端服务器获取内容。

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

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

error code [reason] 。

pass。


vcl_fetch 函数

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

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

error code [reason]。

pass。

deliver。

esi。

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


vcl_deliver 函数

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

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

error code [reason]。

deliver。

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

vcl_error

出现错误时调用此函数。

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

deliver。

restart



2)工作流程概述

   Varnish 与一般服务器软件类似,分为 master 进程和 child 进程。Master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程。Child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配。Child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程。

    接着,开始真正的工作,varnish 的某个负责接收新 HTTP 连接线程开始等待用户,如果有新的 HTTP 连接过来,它总负责接收,然后唤醒某个等待中的线程,并把具体的处理过程交给它。Worker 线程读入 HTTP 请求的 URI计算出响应的hash值,查找已有的 object,如果命中则直接返回并回复用户。如果没有命中,则需要将所请求的内容,从后端服务器中取过来,存到缓存中,然后再回复。

   分配缓存的过程是这样的:它根据所读到 object 的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个 object 的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上,这样做可以减少磁盘碎片。如果缓存已满,就根据 LRU(最近做少使用原则) 机制,把最旧的 object 释放掉。

   释放缓存的过程是这样的:有一个超时线程,检测缓存中所有 object 的生存期,如果超初设定的 TTL(Time To Live)没有被访问,就删除之,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前面或后面的空闲内存块,如果前面或后面的空闲内存和该释放内存是连续的,就将它们合并成更大一块内存。

    整个文件缓存的管理,没有考虑文件与内存的关系,实际上是将所有的 object 都考虑是在内存中,如果系统内存不足,系统会自动将其换到 swap 空间,而不需要 varnish 程序去控制。


四:VCL的内置公共变量

1)当请求到达时,可以使用的公共变量

 

2)对客户端相应时可使用公共变量

3)后端主机获取内容时可使用公共变量


五:varnish试验

1)试验拓扑


2)查看安装的配置文件

[root@varnish ~]# rpm -ql varnish
/etc/logrotate.d/varnish
/etc/rc.d/init.d/varnish #启动脚本
/etc/rc.d/init.d/varnishlog
/etc/rc.d/init.d/varnishncsa
/etc/sysconfig/varnish #启动脚本的配置文件
/etc/varnish #全局配置文件
/etc/varnish/default.vcl #默认VCL
/usr/bin/varnish_reload_vcl #varnish管理工具
/usr/bin/varnishadm
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishreplay
/usr/bin/varnishsizes
/usr/bin/varnishstat
/usr/bin/varnishtest
/usr/bin/varnishtop
/usr/lib64/varnish
/usr/lib64/varnish/libvarnish.so
/usr/lib64/varnish/libvarnishcompat.so
/usr/lib64/varnish/libvcl.so
/usr/lib64/varnish/libvgz.so
/usr/lib64/varnish/vmods
/usr/lib64/varnish/vmods/libvmod_std.so
/usr/sbin/varnishd
/usr/share/doc/varnish-3.0.4
/usr/share/doc/varnish-3.0.4/ChangeLog
/usr/share/doc/varnish-3.0.4/LICENSE
/usr/share/doc/varnish-3.0.4/README
/usr/share/doc/varnish-3.0.4/README.redhat
/usr/share/doc/varnish-3.0.4/examples
/usr/share/doc/varnish-3.0.4/examples/default.vcl
/usr/share/doc/varnish-3.0.4/examples/zope-plone.vcl
/usr/share/man/man1/varnishadm.1.gz #man配置文件
/usr/share/man/man1/varnishd.1.gz
/usr/share/man/man1/varnishhist.1.gz
/usr/share/man/man1/varnishlog.1.gz
/usr/share/man/man1/varnishncsa.1.gz
/usr/share/man/man1/varnishreplay.1.gz
/usr/share/man/man1/varnishsizes.1.gz
/usr/share/man/man1/varnishstat.1.gz
/usr/share/man/man1/varnishtest.1.gz
/usr/share/man/man1/varnishtop.1.gz
/usr/share/man/man3/vmod_std.3.gz
/usr/share/man/man7/varnish-cli.7.gz
/usr/share/man/man7/varnish-counters.7.gz
/usr/share/man/man7/vcl.7.gz
/var/lib/varnish
/var/log/varnish #日志文件

3)修改启动脚本配置文件

[root@varnish sysconfig]# vim /etc/sysconfig/varnish
VARNISH_LISTEN_PORT=80 #这里设置的监听端口设置为80
VARNISH_STORAGE="malloc,64M" #我们这里设置的是64M,因为我们这里是测试环境,在生产环境中可以根据实际需求设置很大

4)启动varnish

[root@varnish ~]# service varnish start
Starting Varnish Cache:                  [确定]

5)配置后端http服务器

[root@web1 ~]# yum install -y httpd
[root@web1 ~]# cat /var/www/html/index.html
<h1>varnish server node1</h1>
[root@web1 ~]# service httpd start
正在启动 httpd:

6)真假vcl配置文件

[root@varnish ~]# cd /etc/varnish/
[root@varnish varnish]# cp default.vcl test.vcl
[root@varnish varnish]# vim test.vcl
backend webserver {
 .host = "172.16.16.1";
 .port = "80";
}
 sub vcl_recv {
 set req.backend = webserver;
}

7)加载vcl配置文件

[root@varnish ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
200
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-358.el6.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-3.0.4 revision 9f83e8f
Type ‘help‘ for command list.
Type ‘quit‘ to close CLI session.
varnish> vcl.load test test.vcl #编译
200
VCL compiled.
varnish> vcl.list
200
active     0 boot
available    0 test
varnish> vcl.use test
200

OK,进行测试一下



如何修改配置文件查看我们的缓存是否命中

1)修改配置文件

[root@varnish varnish]# vim test.vcl
backend default {
 .host = "172.16.16.1";
 .port = "80";
}
 sub vcl_recv {
 set req.backend = webserver;
}
 #修改vcl_deliver增一个响应头部
 sub 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;
    }
 }

第一次加载时缓存X-Cache为Miss(没有被命中).

第二次刷新加载时命中缓存此处的X-Cache为HIT.


如何设置让某个条件不被命中

1)修改配置文件

[root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver {
    .host = "172.16.16.1";
    .port = "80";
}
#设置条件让请求test.html文件时不缓存
 sub vcl_recv {
    if (req.url ~ "^/test.html$") {
        return(pass);
    }
    set req.backend = webserver;
}
 sub 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;
    }
 }
[root@web1 ~]# vim /var/www/html/test.html
<h1>mandela</h1>

2)重新加载配置文件

varnish> vcl.load test2 test.vcl
200
VCL compiled.
varnish> vcl.use test2
200


不管刷新多少次始终是不会对此网页信息进行缓存.


如何根据响应内容作出判断

修改配置文件

[root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver {
    .host = "172.16.16.1";
    .port = "80";
}
sub vcl_recv {
    if (req.url ~ "^/test.html$") {
        return(pass);
    }
    set req.backend = webserver;
}
sub vcl_fetch {
    if (req.request == "GET" && req.url ~ "\.(html|css|js|jpg|jpeg|png|gif)$") {
        set beresp.ttl = 3600s;
    }
}
sub 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;
    }
 }

重新加载文件

varnish> vcl.load test3 test.vcl
200
VCL compiled.
varnish> vcl.use test3
200

varnish如何实现负载均衡及检查后端主机状态

修改配置文件

 
 
 [root@varnish ~]# vim /etc/varnish/test.vcl
backend webserver1 {
    .host = "172.16.16.1";
    .port = "80";
    .probe = {
    .url = "/index.html";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
backend webserver2 {
    .host = "172.16.16.4";
    .port = "80";
    .probe = {
    .url = "/index.html";
    .interval = 1s;
    .window = 3;
    .threshold = 1;
  }
}
director webserver random {
    { .backend = webserver1; .weight = 3; }
    { .backend = webserver2; .weight = 1; }
}
sub vcl_recv {
      set req.backend = webserver;
}
sub 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;
    }
 }

重新装载

varnish> vcl.load test4 test.vcl
200
VCL compiled.
varnish> vcl.use test4
200

 这样后端定义了两个主机16.1和16.2.且实现了轮训调度加缓存机制加后段的安全状态检测,后端的安全状态检测是每一秒检测一次,检测三次不在线就自动下线.判断在线次数只需要判断一次.

varnish> backend.list
200        
Backend name                   Refs   Admin      Probe
default(127.0.0.1,,80)         1      probe      Healthy (no probe)
webserver(172.16.16.1,,80)     4      probe      Healthy (no probe)
webserver1(172.16.16.1,,80)    3      probe      Healthy 3/3
webserver2(172.16.16.4,,80)    3      probe      Healthy 3/3

定义的后端主机分别是16.1和16.4

每隔一秒钟就检测一下后端主机是否在线.200状态码说明主机在线.


OK 我们的varnish配置基本完成.希望大家有些收获.

本文出自 “slayer” 博客,请务必保留此出处http://slayer.blog.51cto.com/4845839/1558268

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。