varnish


        简介 | 安装 | 工作流程 | VCL介绍 | 日志系统



简介:

    varnish是一个web应用加速器也称为cache型的http反向代理,与传统的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等诸多优点,除了它的性能,配置语言VCL使得它可以非常灵活,VCL可以让我们编写请求和响应的处理策略,策略可以决定提供什么服务、从哪获取内容以及请求和响应报头怎样修改。


特点:


    • 重启后缓存数据失效;

    • 利用虚拟内存方式,I/O 性能好;

    • VCL 配置管理比较灵活;

    • 具有强大的管理功能,top、stat、admin、list 等;

    • 状态机设计巧妙,结构清晰;

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


下载安装:    CentOS6.8    varnish-4.0.3-1.el6.x86_64


     CentOS上配置好epel源可直接yum安装:

]# yum isntall varnish

    若想下载较新版本可从官方网站找到yum源:

    http://varnish-cache.org/releases/install_redhat.html#install-redhat


      安装后主要文件及命令:

        主配置文件:

            /etc/sysconfig/varnish  配置varnish工作特性,监听的地址和端口,缓存机制等;

            /etc/varnish/default.vcl 各Child/Cache线程的工作属性,缓存策略配置

        主程序:

            /usr/sbin/varnishd

        CLI命令行接口:

            /usr/bin/varnishadm

        Shared Memory Log交互工具:

            /usr/bin/varnishhist

            /usr/bin/varnishlog

            /usr/bin/varnishncsa

            /usr/bin/varnishstat

            /usr/bin/varnishtop

        测试工具程序:

            /usr/bin/varnishtest

        VCL配置文件重载程序:

            /usr/sbin/varnish_reload_vcl

        服务启动脚本:

            /etc/rc.d/init.d/varnish

    启动varnish:

        ]# varnishd -f /etc/varnishd/default.vcl -s file,/var/varnish_cache,1G\

            -T 127.0.0.0:6081 -a 0.0.0.0:80

        各选项解释:

        -f 指定 varnish 的配置文件位置

        -s 指定 varnish 缓存存储机制,下面有解释

        -T address:port 设定 varnish 的管理地址及其端口,用于 varnishadm 管理

        -a address:port 接收请求的地址及端口,缓存的后方应用为 http 则可将端口设为 80


     注: 一般 varnish 的启动选项定义在 /etc/sysconfig/varnish 文件中,以各变量的值作为运行参数,当使用 service varnish start 方式启动服务时会自动加载该文件,文件内容较为容易理解,需注意最后的 # DAEMON_OPTS="" 该变量可添加启动时的额外选项,如:

DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300" 

以指定最大空闲线程数、最大线程数、线程超时时长等。


...

# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -p thread_pool_min=${VARNISH_MIN_THREADS} \
             -p thread_pool_max=${VARNISH_MAX_THREADS} \
             -p thread_pool_timeout=${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"
#
## Alternative 4, Do It Yourself. See varnishd(1) for more information.
#
# DAEMON_OPTS=""


varnish的缓存存储机制( Storage Types):


    • malloc[,size]

 内存存储,使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象;可能会产生内存碎片,影响性能


    • file[,path[,size[,granularity]]]

 文件存储,黑盒,使用特定单个文件存储全部的缓存数据,并通过操作系统的mmap()系统调用将整个缓存文件映射至内存区域,重启后所有缓存项失效;


    • persistent,path,size

     与file功能相同,黑盒,但可以持久存储数据;目前测试阶段;


可在/etc/sysconfig/varnish文件中定义VARNISH_STORAGE=;或varnishd -s TYPE


Varnish无法追踪某缓存对象是否存入了缓存文件,从而也就无从得知磁盘上的缓存文件是否可用,因此,file存储方法在varnish停止或重启时会清除数据。



设计结构:


varnish详解_第1张图片



工作流程:


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

      Varnish 的某个负责接收新 HTTP 连接线程开始等待用户,如果有新的 HTTP 连接过来,它总负责接收,然后唤醒某个等待中的线程,并把具体的处理过程交给它。Worker 线程读入 HTTP 请求的 URI,查找已有的 object,如果命中则直接返回并回复用户。如果没有命中,则需要将所请求的内容,从后端服务器中取过来,存到缓存中,然后再回复。具体决策操作流程由vcl各状态引擎实现


varnish详解_第2张图片


配置Varnish


VCL简介:

    VCL(varnish configuration language)是 varnish 域专用的配置语言,用来描述请求处理过程、定义数据的存储策略。VCL 语法比较简单,和 C 和 Perl 比较相似。当新的配置被加载时,主控进程会启用vcc将配置文件编译成二进制程序(所以依赖到 gcc 环境),并组织成共享对象(Shared Object)交由Child进程加载使用,若编译失败会返回相应错误,varnish运行时可随时加载配置文件。


想要配置varnish正常工作。需先了解varnish 的配置语言VCL,“域专用”指的是有些数据仅出现于特定的状态中。

    • VCL文件以 vcl 4.0 为起始;    /etc/varnish/default.vcl

    • //,#,/*..*/ 为注释

    • sub定义一个subroutings

    • 没有循环,有限状态

    • 以一个关键词作为返回状态参数以表示下一步动作,即:return(action)

    • 域专用的配置语言

    • 操作符:=、==、~、!、&&、||、<、>=


示例:    该为varnish默认策略中的一段,表示若请求方法为GET、HEAD则直接交由后端主机处理

        若请求包含认证或Cookie则直接交由后端主机处理

sub vcl_recv {
    ...
    if (req.method != "GET" && req.method != "HEAD") {
        /* We only deal with GET and HEAD by default */
        return (pass);
    }
    if (req.http.Authorization || req.http.Cookie) {
        /* Not cacheable by default */
        return (pass);
    }
    ...
}


vcl state engine 状态引擎:

vcl_recv:用于接收和处理请求;当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求;

vcl_pipe:用于将请求直接传递至后端主机,并将后端响应原样返回客户端;

vcl_pass:用于将请求直接传递至后端主机,但后端主机的响应并不缓存直接返回客户端;

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

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

vcl_hash:在vcl_recv调用后为请求创建一个hash值时,调用此函数;此hash值将作为varnish中搜索缓存对象的key;

vcl_purge:pruge操作执行后调用此函数,可用于构建一个响应;

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

vcl_backend_fetch:向后端主机发送请求前,调用此函数,可修改发往后端的请求;

vcl_backend_response:获得后端主机的响应后,可调用此函数;

vcl_backend_error:当从后端主机获取源文件失败时,调用此函数;

vcl_init:VCL加载时调用此函数,经常用于初始化varnish模块(VMODs)

vcl_fini:当所有请求都离开当前VCL,且当前VCL被弃用时,调用此函数,经常用于清理varnish模块;

vcl_synth:自定义返回页面,可在purge操作时调用。


主要语法:


sub subroutine {
...
}
if CONDITION {
...
} else {
...
}
return(), hash_data()


配置示例:


  

]# vi /etc/varnish/default.vcl

]# varnish_reload_vcl



后端主机健康监测:

probe check {        定义该检查的名称为 check ,当后端主机较多时,直接在 backend 中调用即可。
    .url = "/.healthcheck.html";
    .window = 5;    基于最近多少次探测
    .threshold = 4;  最近.window定义的检查次数中.threshhold定义的次数成功则为健康
    .interval = 2s;    检查时间间隔
    .timeout = 1s;     超时时长
    .expected_response:  期望的响应码,默认为200;
}


声明并初始化一个后端对象:

backend web1 { 
   .host = "10.1.235.33"; 
   .port = "80"; 
   .probe = check;    调用该检查机制
}
backend web2 { 
   .host = "10.1.235.66"; 
   .port = "80"; 
   .probe = check;
}


清除图片类请求响应首部cookie字段,取消私有标识,并指定可缓存时长ttl (增加)

sub vcl_backend_response {
    if (bereq.http.cache-control !~ "s-maxage") {
        if (bereq.url ~ "(?i)\.jpg$") {        (?i) 表示不区分大小写
            set beresp.ttl = 7200s;
        unset beresp.http.Set-Cookie;
    }
        if (bereq.url ~ "(?i)\css&") {
            set beresp.ttl = 7200s;
            unset beresp.http.Set-Cookie;
        }
    }
}


缓存对象修剪:

purge 自定义的方法,通常请求指定url缓存

ban 通常用来清理表达式匹配的缓存项

acl purge {acl控制,定义可清理缓存的主机地址,防止用户操作
"localhost";
"10.1.235.6"/16;
}
sub vcl_recv {
if (req.method == "PURGE") {     若方法为 PURGE 则执行清理操作
if (!client.ip ~ purge) {    限制来源
return(synth(405,"Not allowed."));
}
    return (purge);    定义下一步
}
}
sub vcl_purge {
return (synth(200,"Purged."));    返回 sycth 定义的页面
}


当有多个backend:动静分离

设定多个后端主机

backend default {
.host = "10.1.235.66";
.port = "80"
}
backend phpsrv {
.host = "10.1.235.77";
.port = "80";
}


接收时策略,对不同类型的资源请求分发到专用的后端服务器上

vcl_recv {
   if (req.url ~ "(?i)\.php$") {
       set req.backend_hint = "phpsrv";
   } else {
       set req.backend_hint = "default";
   }
}


实现负载均衡: 缓存可能导致无负载均衡效果,可定义不可缓存文件或目录测试


import directors;    # 需先加载 directors

定义后端主机:

backend web1 {
   .host = "10.1.235.33";
}
backend web2 {
   .host = "10.1.235.66";
}


定义后端服务器组:

sub vcl_init {
   new websrv = directors.round_robin();    round_robin|random 调度算法较少
   websrv.add_backend(web1);
   websrv.add_backend(web2);
}


分发请求时调用该组:

sub vcl_recv {
   # send all traffic to the bar director:
   set req.backend_hint = websrv.backend();
}



日志系统:


    varnish 默认将日志记录在一段共享内存中 shared memory log ,内存空间分为两部分,计数器和日志信息,提供非常详细的信息,这提高了性能,但不易于查找问题,记录在内存中的数据无法长时间保存。

    内存中日志区域大小有限,如果不使用一个程序将日志信息保存到磁盘上,日志数据将会被不断覆盖。


日志查看命令:


]# varnishlog    动态持续更新显示日志信息


]# varnishtop    对日志信息做了整理排序

-1 仅输出一次静态信息后退出    数字 1

-i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;

-I <[taglist:]regex>

-x taglist:排除列表

-X <[taglist:]regex>


]# varnishstat    缓存状态查看

-1 -f FILED_NAME 

-l:可用于-f选项指定的字段名称列表;


日志记录服务:

varnishlog    以varnishlog命令输出的格式记录日记,内容较多,不易读

varnishncsa    以类似http访问日志格式记录日志,combined 日志格式


一般可开启 varnishncsa 服务将日志记录于磁盘上

]# service varnishncsa start

    默认保存于 /var/log/varnish/varnishncsa.log