Varnish基础原理及简单配置
来源:互联网 发布:怎样辨别淘宝评论真假 编辑:程序博客网 时间:2024/06/05 23:53
<html><body><h1 style="text-align:center;color:red">Varnish基础原理及简单配置</h1><ol style="font-size:20px;font-weight:bold"><style type="text/css"> p{ text-indent:2em;} </style><li>Varnish简介:<br /><p >Varnish是一填款高性能的开源HTTP加速器,同时作为http反向缓存补充资料: <a href="http://book.varnish-software.com/4.0/">http://book.varnish-software.com/4.0/</a></p >特点<ul><p><li>Varnis可以使用内存也可以使用硬盘进行数据缓存<li>支持虚拟内存的使用<li>有精确的时间管理机制<li>状态引擎架构:通过特定的配置语言设计不同的语句<li>以二叉堆格式管理数据</p></ul>优势:<ul><p><li>varnish访问速度快,因为采用了“Visual Page Cache”技术,在读取数据时直接从内存中读取<li>varnish支持更多的并发连接,因为varnish的TCP连接比squid快<li>varnish通过管理端口,使用正则表达式批量的清除部分缓存</p></ul>劣势<ul><p><li>进程一旦crash或重启,缓存的数据将从内存中完全释放,导致后端服务器压力过大,重新启动的热身时间,需要耗时数小时不等<li>在多台varnish实现负载均衡时,每次请求都会落到不同的varnish服务器中,造成url请求可能会穿透到后端<br /><br />解决方案:<br /><p> A:在varnish的后端添加squid/nginx代理,这样防止了当varnish缓存被清空时,瞬间大量的请求发往web服务器<br /></p><p> B:在负载均衡上做hash request_url,让单个url请求固定请求到一台varnish服务器上</p></p></ul><br /><li>varnish组成:<p>Management进程,用来管理进程,对child进程进行管理,同时对vcl配置进行编译<br /></p><p>child进程,子进程,生成线程池,负责处理用户请求</p>阶段:<p><ul><li>req:处理客户端发送的请求时使用<li>bereq:处理varnish向后端服务器发送的请求时使用<li>beresp:处理后端服务器响应时使用,用于varnish未缓存前<li>resp:处理返回给客户端的响应时使用<li>obj:处理存储在内存中的对象时使用</ul></p><br /><br />varnish工作流程图:<li>客户端发送的请求对象<table border="40" width="600" cellpadding="20" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">阶段对象</td><td>说明</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req</td><td>整个HTTP请求数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">req.backend_hint</td><td>指定请求的后端节点</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.http</td><td>对应请求HTTP的header</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.can_gzip</td><td>客户端是否接受GZIP传输编码</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.hash_always_miss</td><td>是否强制不命中高速缓存</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.hash_ignore_busy</td><td>忽略缓存中忙碌的对象,多台缓存时可以避免死锁</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.method</td><td>请求类型(如GET,POST)</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.restarts</td><td>重新启动次数,默认最大值是4</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.ttl</td><td>缓存剩余时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.url</td><td>请求的url</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.xid</td><td>唯一ID</td></tr></table><li>发送到后端的请求对象<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq</td><td>整个后端请求后数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.backend</td><td>所请求后端节点配置</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.between_bytes_timeout</td><td>从后端每接收一个字节之间的等待时间(秒)</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.connect_timeout</td><td>连接后端等待时间(秒),最大等待时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.first_byte_timeout</td><td>等待后端第一个字节时间(秒),最大等待时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.http</td><td>对应发送到后端HTTP的header信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.method</td><td>发送到后端的请求类型</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.uncacheable</td><td>无缓存这个请求</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.url</td><td>发送到后端请求的URL</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.xid</td><td>请求唯一ID</td></tr></table><li>后端响应请求对象<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp</td><td>整个后端响应HTTP数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.backend.ip</td><td>后端响应的IP</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.backend.name</td><td>响应后端配置节点的name</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.do_gunzip</td><td>默认为false,缓存前解压该对象</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.do_gzip</td><td>默认为false,缓存前压缩该对象</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.grace</td><td>设置当前对象缓存过期后可额外宽限时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.http</td><td>对应的HTTP请求header</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.keep</td><td>对象缓存后带保持时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.reason</td><td>由服务器返回的HTTP状态信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.status</td><td>由服务器返回的状态码</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.storage_hint</td><td>指定保存的特定存储器</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.ttl</td><td>该对象缓存的剩余时间,指定统一缓存剩余时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.uncacheable</td><td>继承bereq.uncacheable,是否不缓存</td></tr></table><li>高速缓存对象,缓存后端响应请求内容<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.grace</td><td>该对象额外宽限时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.hits</td><td>缓存命中次数</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.http</td><td>对应HTTP的header</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">obj.reason</td><td>服务器返回的HTTP状态信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.status</td><td></td>服务器返回的状态码</tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.ttl</td><td>该对象缓存剩余时间秒</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.uncacheable</td><td>不缓存对象</td></tr></table><li>返回给客户端的响应对象<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp</td><td>整个响应HTTP数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.http</td><td>对应HTTP的hearder</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.proto</td><td>编辑响应的HTTP协议版本</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.reason</td><td>将要返回的HTTP状态信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.status</td><td>将要返回的HTTP状态码</td></tr></table><br /><br /><li>运算符:<br /><ul type="square"> <li>=:赋值运算<br /> <li>==:相等比较<br /> <li>~ :匹配,可以使用正则表达式,或访问控制列表<br /> <li>!~:不匹配,可以使用正则表达式,或访问控制列表<br /> <li>! :非<br /> <li>&&:逻辑与<br /> <li>||:逻辑或<br /></ul><br /><br /><li>功能语句与对象<br /> 一般功能语句都用于匹配对象,就是对某个对象实现什么操作<ul type="square"> <li>ban():清除指定对象缓存<br /> <li>ban_url(regex):可以清除被此处匹配到的缓存<br /> <li>call():调用子程序<br /> <li>hash_data():生成hash键值,只能在vck_hash子程序中使用<br /> <li>new():创建一个vcl对象,只能在vcl_init子程序中使用<br /> <li>return():结束当前子程序并执行下一步动作<br /> <li>rollback():恢复http头到原来的状态,现在使用std.rollback()代替<br /> <li>synthetic():合成器,用于自定义一个响应内容,只能在vcl_synth和vcl_backend_error子程序中使用<br /> <li>regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite<br /> <li>regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;<br /></ul><li><ul>return的常用动作<br /> 语法:return (action)<br /> <li type="square">abandon:放弃处理,并生成一个错误 <li type="square">deliver:交付至后端处理 <li type="square">fetch:从后端取出响应对象 <li type="square">hash:哈希缓存处理 <li type="square">lookup:从缓存中查找应答数据并返回,如果查找不到,则调用pass函数,从后端服务器调用数据 <li type="square">ok:继续执行 <li type="square">pass:绕过缓存,直接向后端服务器调用数据 <li type="square">pipe: 建立客户端和后端服务器之间的直接连接,之后客户端的所有请求都直接发送给服务器,绕过varnish,不再由varnish检查请求,直到断开连接 <li type="square">purge:清除缓存对象,构建响应 <li type="square">restart:重新开始 <li type="square">retry: 重试后端处理 <li type="square">synth 合成响应报文,响应客户端 </ul><br /><ul style="color:green">varnish中内置子程序:<br /> <li type="square">子进程也叫状态引擎,每一个状态引擎均有自己限定的返回动作return,不同的动作将调用对应下一个状态引擎。</li><br /> <li type="square">我们可以把一个请求分为多个阶段,每个阶段都会调用不同的状态引擎去操作,这样,我们只编写出相应的状态引擎,就可认控制每个请求阶段</li><br /> <li type="square">varnish内置子程序均有自己限定的返回动作return,不同的动作将调用对应下一个子程序 每个子程序都需要通过关键字sub进行定义</li><br /></ul><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_recv子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">开始处理请求,通过return(动作);选择varnish处理模式,默认进入hash缓存模式(即return(hash);),缓存时间为配置default_ttl(默认为120秒)过期保持时间default_grace(过期容忍时间,默认为10秒)。该子程序一般用于模式选择,对象缓存及信息修改,后端节点修改,终止请求等操作</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:purple"> <td width="200">返回值:synth,pass,pipe,hash,pruge</td></tr></td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:purple"> <td width="200">vcl_pipe子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">pipe模式处理,该模式主要用于直接取后端响应内容返回客户端,可定义响应内容返回客户端。该子程序一般用于需要及时且不作处理的后端信息,取出后端响应内容后直接交付到客户端不进入vcl_deliver子程序处理</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:purple"> <td width="200">返回值:synth,pipe</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_pass子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">pass模式处理,该模式类似hash缓存模式,仅不做缓存处理</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:synth,fetch:继续pass模式,进入后端vcl_backend_fetch子程序,默认返回值</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_hit子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">hash缓存模式时存在hash缓存时调用,用于缓存处理,可放弃或修改缓存</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:restart,deliver默认返回值,synth</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_miss子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">hash缓存模式时不存在hash缓存时调用,用于判断性的选择进入后端取响应内容,可以修改为pass模式</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:restart重启请求,synth,pass,fetch:正常取后端内容再缓存,进入vcl_backend_fetch子程序,默认返回值</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_hash</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">hash缓存模式,生成hash值作为缓存查找键名提取缓存内容,主要用于缓存hash键值处理,可使用hash_data(string)指定键值组成结构,可在同一页面通过IP或Cookie生成不同的缓存键值</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:lookup:查找缓存对象,存在缓存进入vcl_hit子程序,不存在缓存进入vcl_miss子程序,当使用了purge清理模式时会进入vcl_purge子程序,默认返回值</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">acl_purge子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">清理模式,当查找到对应的缓存时清除并调用,用于请求方法清除缓存,并报告</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:synth,restart</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_deliver子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">客户端交付子程序,在vcl_backend_response子程序后调用(非pipe模式),或vcl_hit子程序后调用,可用于追加响应头信息,cookie等内容</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,restart</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_backend_fetch子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">发送后端请求之前调用,可用于改变请求地址或其它信息,或放弃请求</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:fetch:正常发送请求到后端取出响应内容,进入vcl_backend_response子程序,默认返回值,abandon</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_backend_redponse子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">后端响应后调用,可用于修改缓存时间及缓存相关信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,abandon,retry:重试后端请求,重试计数器加1,当超过配置中max_retries值时会报错并进入vcl_backend_error子程序</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_backend_error子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">后端处理失败调用,异常页面展示效果处理,可自定义错误响应内容,或修改beresp.status与beresp.http.Location重定向等</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,retry</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_synth子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">自定义响应内容,可以通过synthetic()和返回值synth调用,这里可以自定义异常显示内容,也可以修改resp.status与resp.http.Location重定向</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,restart</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_init子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">加载vcl时最先调用,用于初始化VMODs,该子程序不参与请求处理,仅在vcl加载时调用一次</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:ok</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_fini子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">卸载当前vcl配置时调用,用于清理VMODs,该子程序不参与请求处理,仅在vcl正常丢弃后调用</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:ok</td></tr></table><br /><br /><li><p style="font-size:25px;font-weight:bold;color:green">后端服务器定义:</p><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">属性</td><td>说明</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.host= "IP";</td><td>要转向主机(即后端主机)的IP或域名,必填键值对</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.port = "80";</td><td>主机连接端口号或协议名(HTTP等),默认80</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.connect_timeout = 0.5s;</td><td>连接后端主机的超时时长</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.first_byte_timeout = 2s;</td><td>等待从后端返回的第一个字节时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.between_bytes_timeout = 2s;</td><td>每接收一个字节之间等待时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.probe = probe_name</td><td>监控后端主机的状态,指定外部监控name或者内部直接添加</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.max_connections = 1000;</td><td>设置最大并发连接数,超过这个数后连接就会失败</td></tr></table><li><p style="font-size:25px;font-weight:bold;color:green">监视器定义</p><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.url = "/";</td><td>指定监控入口地址,默认为“/”</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.request = "";</td><td>指定监控请求入口地址,比.url优先级高</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.timeout = "";</td><td>超时时长</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.window = "";</td><td>基于最近的多少次检查来判断其健康状态,默认为8</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.threshold = "";</td><td>最近.window中定义的这么次检查中至少有.threshold定义的次数是成功的,默认是3</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.interval = "";</td><td>检测频度,默认为5秒</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.initial = -1</td><td>window中有几次是良好启用此节点</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.expected_reponse = "";</td><td>期望的响应码,默认为200</td></tr></table><br /><li>检测实例:<pre>probe check { .url = "/"; .timeout = 2s; .interval = 2s; <code style="color:red;font-size:20px">//这里又引入了新的问题,虽然会去自动检测后端主机的健康性,但是后端主机会记录日志的,如果设定的时间过短,会增大后端服务器的磁盘压力,过长,则会使用户感觉不好,设一个稳点的值</code> .window = 8; .threshold = 6;}backend websrv { .host = "172.16.252.113"; .port = "80"; .max_connections = 500; .probe = check;}<code style="color:green">>backend.list</code>200 Backend name Refs Admin Probewebsrv(172.16.252.113,,80) 4 probe Sick 5/8 //检测出来的效果sick生病了default(127.0.0.1,,8080) 4 probe Healthy (no probe)backend.list200 Backend name Refs Admin Probewebsrv(172.16.252.113,,80) 4 probe Sick 4/8default(127.0.0.1,,8080) 4 probe Healthy (no probe)backend.list200 </pre><br /><br /><li><p style="font-size;20px;font-weight:bold;color:blue">PURGE和BAN操作,来清理特定的缓存,也可以在命令行中执行</p><pre>acl purgers { "127.0.0.1"; "192.168.0.0"/24;}sub vcl_recv { # allow PURGE from localhost and 192.168.0... if (req.method == "PURGE") { if (!client.ip ~ purgers) { return (synth(405, "Purging not allowed for " + client.ip)); } return (purge); }}sub vcl_purge { return (synth(200,"Purged,now!"));# set req.method = "GET";# return (restart);} if (req.method == "BAN") { if (!client.ip ~ purgers) { return (synth(405,"Banning not allowd for" + client.ip)); }<code style="color:red"> ban(" req.http.host == " + req.http.host + " && req.url == " + req.url); </code> //运算符边上必须有空格,要不然会实现不了功能的 return (synth(200,"Ban added.")); }操作:<code style="color:green">~]# varnish -S /etc/varnish/secret -T 127.0.0.1:6082</code>vcl.load test1 default.vclvcl.use test1 也可在此操作清除缓存:ban req.url ~ .js$ //清除以.js结尾的文件缓存,毕竟可以用正则表达式,多方便客户端操作:<code style="color:green">~]# crul -I http://172.16.254.35</code>HTTP/1.1 200 OKServer: nginx/1.10.2Date: Tue, 27 Jun 2017 09:27:38 GMTContent-Type: text/htmlContent-Length: 17Last-Modified: Tue, 27 Jun 2017 06:21:47 GMTETag: "5951f97b-11"X-Varnish: 3964978Age: 0Via: 1.1 varnish-v4X-Cache: Miss via172.16.254.35 //没有命中Connection: keep-alive<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>....X-Cache: Hit via172.16.254.35 //命中...进行PURGE操作:<code style="color:green">~]# curl -X PURGE http://172.16.254.35/index.html</code>...Error 405 Purging not allowed for172.16.251.81...再次访问:<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>...X-Cache: Miss via172.16.254.35 //不能命中缓存...<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>....X-Cache: Hit via172.16.254.35 //命中...进行BAN操作:<code style="color:green">~]# curl -X BAN http://172.16.254.35/index.html</code>...Error 405 Purging not allowed for172.16.251.81...再次访问:<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>...X-Cache: Miss via172.16.254.35 //不能命中缓存...<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>....X-Cache: Hit via172.16.254.35 //命中... </pre><br /><br /><li>实例:在缓存中,强制对某类资源的请求不检查缓存:<pre>vcl_recv { if (req.url ~ "(?i)^/(login|admin)") { //(?i)不区分字符大小写 return(pass); }} </pre><br /><li>实例:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;定义在vcl_backend_response中<pre>if (beresp.http.cache-control !~ "s-maxage") { //如果后端服务器没有给缓存时长 if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") { //同时匹配以.jpg...结尾的文件 unset beresp.http.Set-Cookie; <code style="color:red">//说明:默认情况下,varnish不缓存从后端响应的http头中带有Set-Cookie的对象。如果客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求递送至后端服务器上</code> set beresp.ttl = 3600s; //设置后端响应首部的生存时长为1h }}</pre><br /><li>实例:将真实的客户IP地址转移至后端服务器上,以便日志记录<pre>if (req.restarts == 0) { if (req.http.X-Fowarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip; } else { set req.http.X-Forwarded-For = client.ip; }}</pre><br /><br /><li>最后的一个整体笔记:<pre style="background:black;color:white;font-size:20px">import directors; <code style="color:red;font-size:20px">//负载均衡集群需要directors模块支持,import directors</code>acl purgers { <code style="color:red;font-size:20px">//对缓存资源进行控制</code> "127.0.0.1"; "172.16.0.0"/16;}probe check { <code style="color:red;font-size:20px">//对后端服务器的状态检测</code> .url = "/"; .timeout = 2s; .interval = 10s; .window = 8; .threshold = 6;}backend websrv { <code style="color:red;font-size:20px">//定义后端主机的属性</code> .host = "172.16.252.113"; .port = "80"; .max_connections = 500; .port = "80"; .max_connections = 500; .probe = check; <code style="color:red;font-size:20px">//执行健康状态检测</code>}backend websrv2 { .host = "172.16.250.84"; .port = "80"; .probe = check;}# Default backend definition. Set this to point to your content server.backend default { .host = "127.0.0.1"; .port = "8080";}sub vcl_init { <code style="color:red;font-size:20px">//初始化子程序创建后端主机组,即directors</code> new WEBGROUP = directors.round_robin(); <code style="color:red;font-size:20px">//使用new关键字创建director对象,使用round_robin算法</code> WEBGROUP.add_backend(websrv); WEBGROUP.add_backend(websrv2); WEBGROUP.add_backend(websrv); WEBGROUP.add_backend(websrv2);}sub vcl_recv { <code style="color:red;font-size:20px">//接受请求子程序</code> set req.backend_hint = WEBGROUP.backend(); <code style="color:red;font-size:20px">//调用后端主机组</code> if (req.url ~ "(?i)\.(JPG|PNG|GIF)") { <code style="color:red;font-size:20px">//对几种图片不进行缓存查找</code> return(pass); } if (req.restarts == 0) { <code style="color:red;font-size:20px">//IP地址转移</code> 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; } } if (req.method == "PURGE") { <code style="color:red;font-size:20px">//对某个缓存对象进行清理操作</code> if (!client.ip ~ purgers) { return (synth(405,"Purging not allowed for" + client.ip)); } return (purge); <code style="color:red;font-size:20px">//去往purge子程序操作</code> } if (req.method == "BAN") { <code style="color:red;font-size:20px">//清理某一类缓存对象</code> if (!client.ip ~ purgers) { return (synth(405,"Banning not allowd for" + client.ip)); } ban("req.http.host == " + req.http.host + " && req.url == " + req.url);<code style="color:red;font-size:20px">//清除host+url的对象</code> return (synth(200,"Ban added.")); }# if (req.url ~ "(?i)\.php$") { <code style="color:red;font-size:20px">//以.php请求至后端</code># set req.backend_hint = websrv;# } else {# set req.backend_hint = default;# }}sub vcl_purge { <code style="color:red;font-size:20px">//purge子程序</code> return (synth(200,"Purged"));<code style="color:red;font-size:20px">//合成信息,并返回值</code># set req.method = "GET";<code style="color:red;font-size:20px">//将请求方法设置成GET</code># return (restart);<code style="color:red;font-size:20px">//在发还给客户端,让客户端重新来取</code>}sub vcl_backend_response { # Happens after we have read the response headers from the backend. # # Here you clean the response headers, removing silly Set-Cookie headers # and other mistakes your backend does.}sub vcl_deliver { <code style="color:red;font-size:20px">//发送给客户的数据报文</code> if (obj.hits>0) { <code style="color:red;font-size:20px">//测试用,如果 有缓存,就把X-Cache首部信息发给客户端</code> set resp.http.X-Cache = "Hit via" + server.ip; } else { set resp.http.X-Cache = "Miss via" + server.ip; }}</pre><br /><br /><p style="font-size:25px;color:green">varnish日志区域:<br /><style type="text/css"> p{ text-indent:2em;} </style>1、varnishstat - Varnish Cache statistics<br /> <p> -1 //显示一次<br /></p><p> -1 -f FILED_NAME </p><p> -l:可用于-f选项指定的字段名称列表;</p> <p> MAIN.cache_hit </p><p> MAIN.cache_miss</p> <p> # varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss</p><p> # varnishstat -l -f MAIN -f MEMPOOL</p> <p> 2、varnishtop - Varnish log entry ranking</p><p> -1 Instead of a continously updated display, print the statistics once and exit.</p><p> -i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;</p><p> -I <[taglist:]regex></p><p> -x taglist:排除列表</p><p> -X <[taglist:]regex></p> <p> 3、varnishlog - Display Varnish logs</p> <p> 4、 varnishncsa - Display Varnish logs in Apache / NCSA combined log format</p></p><code style="font-size:20px;color:green">systemctl start varnishncsa.service //开启日志功能服务</code></ol></body></html> <html><body><h1 style="text-align:center;color:red">Varnish基础原理及简单配置</h1><ol style="font-size:20px;font-weight:bold"><style type="text/css"> p{ text-indent:2em;} </style><li>Varnish简介:<br /><p >Varnish是一填款高性能的开源HTTP加速器,同时作为http反向缓存补充资料: <a href="http://book.varnish-software.com/4.0/">http://book.varnish-software.com/4.0/</a></p >特点<ul><p><li>Varnis可以使用内存也可以使用硬盘进行数据缓存<li>支持虚拟内存的使用<li>有精确的时间管理机制<li>状态引擎架构:通过特定的配置语言设计不同的语句<li>以二叉堆格式管理数据</p></ul>优势:<ul><p><li>varnish访问速度快,因为采用了“Visual Page Cache”技术,在读取数据时直接从内存中读取<li>varnish支持更多的并发连接,因为varnish的TCP连接比squid快<li>varnish通过管理端口,使用正则表达式批量的清除部分缓存</p></ul>劣势<ul><p><li>进程一旦crash或重启,缓存的数据将从内存中完全释放,导致后端服务器压力过大,重新启动的热身时间,需要耗时数小时不等<li>在多台varnish实现负载均衡时,每次请求都会落到不同的varnish服务器中,造成url请求可能会穿透到后端<br /><br />解决方案:<br /><p> A:在varnish的后端添加squid/nginx代理,这样防止了当varnish缓存被清空时,瞬间大量的请求发往web服务器<br /></p><p> B:在负载均衡上做hash request_url,让单个url请求固定请求到一台varnish服务器上</p></p></ul><br /><li>varnish组成:<p>Management进程,用来管理进程,对child进程进行管理,同时对vcl配置进行编译<br /></p><p>child进程,子进程,生成线程池,负责处理用户请求</p>阶段:<p><ul><li>req:处理客户端发送的请求时使用<li>bereq:处理varnish向后端服务器发送的请求时使用<li>beresp:处理后端服务器响应时使用,用于varnish未缓存前<li>resp:处理返回给客户端的响应时使用<li>obj:处理存储在内存中的对象时使用</ul></p><br /><br />varnish工作流程图:<li>客户端发送的请求对象<table border="40" width="600" cellpadding="20" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">阶段对象</td><td>说明</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req</td><td>整个HTTP请求数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">req.backend_hint</td><td>指定请求的后端节点</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.http</td><td>对应请求HTTP的header</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.can_gzip</td><td>客户端是否接受GZIP传输编码</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.hash_always_miss</td><td>是否强制不命中高速缓存</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.hash_ignore_busy</td><td>忽略缓存中忙碌的对象,多台缓存时可以避免死锁</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.method</td><td>请求类型(如GET,POST)</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.restarts</td><td>重新启动次数,默认最大值是4</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.ttl</td><td>缓存剩余时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.url</td><td>请求的url</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">req.xid</td><td>唯一ID</td></tr></table><li>发送到后端的请求对象<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq</td><td>整个后端请求后数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.backend</td><td>所请求后端节点配置</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.between_bytes_timeout</td><td>从后端每接收一个字节之间的等待时间(秒)</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.connect_timeout</td><td>连接后端等待时间(秒),最大等待时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.first_byte_timeout</td><td>等待后端第一个字节时间(秒),最大等待时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.http</td><td>对应发送到后端HTTP的header信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.method</td><td>发送到后端的请求类型</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.uncacheable</td><td>无缓存这个请求</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.url</td><td>发送到后端请求的URL</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">bereq.xid</td><td>请求唯一ID</td></tr></table><li>后端响应请求对象<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp</td><td>整个后端响应HTTP数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.backend.ip</td><td>后端响应的IP</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.backend.name</td><td>响应后端配置节点的name</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.do_gunzip</td><td>默认为false,缓存前解压该对象</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.do_gzip</td><td>默认为false,缓存前压缩该对象</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.grace</td><td>设置当前对象缓存过期后可额外宽限时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.http</td><td>对应的HTTP请求header</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.keep</td><td>对象缓存后带保持时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.reason</td><td>由服务器返回的HTTP状态信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.status</td><td>由服务器返回的状态码</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.storage_hint</td><td>指定保存的特定存储器</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.ttl</td><td>该对象缓存的剩余时间,指定统一缓存剩余时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">beresp.uncacheable</td><td>继承bereq.uncacheable,是否不缓存</td></tr></table><li>高速缓存对象,缓存后端响应请求内容<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.grace</td><td>该对象额外宽限时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.hits</td><td>缓存命中次数</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.http</td><td>对应HTTP的header</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">obj.reason</td><td>服务器返回的HTTP状态信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.status</td><td></td>服务器返回的状态码</tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.ttl</td><td>该对象缓存剩余时间秒</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">obj.uncacheable</td><td>不缓存对象</td></tr></table><li>返回给客户端的响应对象<table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp</td><td>整个响应HTTP数据结构</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.http</td><td>对应HTTP的hearder</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.proto</td><td>编辑响应的HTTP协议版本</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.reason</td><td>将要返回的HTTP状态信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"><td width="200">resp.status</td><td>将要返回的HTTP状态码</td></tr></table><br /><br /><li>运算符:<br /><ul type="square"> <li>=:赋值运算<br /> <li>==:相等比较<br /> <li>~ :匹配,可以使用正则表达式,或访问控制列表<br /> <li>!~:不匹配,可以使用正则表达式,或访问控制列表<br /> <li>! :非<br /> <li>&&:逻辑与<br /> <li>||:逻辑或<br /></ul><br /><br /><li>功能语句与对象<br /> 一般功能语句都用于匹配对象,就是对某个对象实现什么操作<ul type="square"> <li>ban():清除指定对象缓存<br /> <li>ban_url(regex):可以清除被此处匹配到的缓存<br /> <li>call():调用子程序<br /> <li>hash_data():生成hash键值,只能在vck_hash子程序中使用<br /> <li>new():创建一个vcl对象,只能在vcl_init子程序中使用<br /> <li>return():结束当前子程序并执行下一步动作<br /> <li>rollback():恢复http头到原来的状态,现在使用std.rollback()代替<br /> <li>synthetic():合成器,用于自定义一个响应内容,只能在vcl_synth和vcl_backend_error子程序中使用<br /> <li>regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite<br /> <li>regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;<br /></ul><li><ul>return的常用动作<br /> 语法:return (action)<br /> <li type="square">abandon:放弃处理,并生成一个错误 <li type="square">deliver:交付至后端处理 <li type="square">fetch:从后端取出响应对象 <li type="square">hash:哈希缓存处理 <li type="square">lookup:从缓存中查找应答数据并返回,如果查找不到,则调用pass函数,从后端服务器调用数据 <li type="square">ok:继续执行 <li type="square">pass:绕过缓存,直接向后端服务器调用数据 <li type="square">pipe: 建立客户端和后端服务器之间的直接连接,之后客户端的所有请求都直接发送给服务器,绕过varnish,不再由varnish检查请求,直到断开连接 <li type="square">purge:清除缓存对象,构建响应 <li type="square">restart:重新开始 <li type="square">retry: 重试后端处理 <li type="square">synth 合成响应报文,响应客户端 </ul><br /><ul style="color:green">varnish中内置子程序:<br /> <li type="square">子进程也叫状态引擎,每一个状态引擎均有自己限定的返回动作return,不同的动作将调用对应下一个状态引擎。</li><br /> <li type="square">我们可以把一个请求分为多个阶段,每个阶段都会调用不同的状态引擎去操作,这样,我们只编写出相应的状态引擎,就可认控制每个请求阶段</li><br /> <li type="square">varnish内置子程序均有自己限定的返回动作return,不同的动作将调用对应下一个子程序 每个子程序都需要通过关键字sub进行定义</li><br /></ul><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_recv子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">开始处理请求,通过return(动作);选择varnish处理模式,默认进入hash缓存模式(即return(hash);),缓存时间为配置default_ttl(默认为120秒)过期保持时间default_grace(过期容忍时间,默认为10秒)。该子程序一般用于模式选择,对象缓存及信息修改,后端节点修改,终止请求等操作</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:purple"> <td width="200">返回值:synth,pass,pipe,hash,pruge</td></tr></td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:purple"> <td width="200">vcl_pipe子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">pipe模式处理,该模式主要用于直接取后端响应内容返回客户端,可定义响应内容返回客户端。该子程序一般用于需要及时且不作处理的后端信息,取出后端响应内容后直接交付到客户端不进入vcl_deliver子程序处理</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:purple"> <td width="200">返回值:synth,pipe</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_pass子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">pass模式处理,该模式类似hash缓存模式,仅不做缓存处理</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:synth,fetch:继续pass模式,进入后端vcl_backend_fetch子程序,默认返回值</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_hit子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">hash缓存模式时存在hash缓存时调用,用于缓存处理,可放弃或修改缓存</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:restart,deliver默认返回值,synth</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_miss子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">hash缓存模式时不存在hash缓存时调用,用于判断性的选择进入后端取响应内容,可以修改为pass模式</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:restart重启请求,synth,pass,fetch:正常取后端内容再缓存,进入vcl_backend_fetch子程序,默认返回值</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_hash</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">hash缓存模式,生成hash值作为缓存查找键名提取缓存内容,主要用于缓存hash键值处理,可使用hash_data(string)指定键值组成结构,可在同一页面通过IP或Cookie生成不同的缓存键值</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:lookup:查找缓存对象,存在缓存进入vcl_hit子程序,不存在缓存进入vcl_miss子程序,当使用了purge清理模式时会进入vcl_purge子程序,默认返回值</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">acl_purge子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">清理模式,当查找到对应的缓存时清除并调用,用于请求方法清除缓存,并报告</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:synth,restart</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_deliver子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">客户端交付子程序,在vcl_backend_response子程序后调用(非pipe模式),或vcl_hit子程序后调用,可用于追加响应头信息,cookie等内容</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,restart</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_backend_fetch子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">发送后端请求之前调用,可用于改变请求地址或其它信息,或放弃请求</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:fetch:正常发送请求到后端取出响应内容,进入vcl_backend_response子程序,默认返回值,abandon</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_backend_redponse子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">后端响应后调用,可用于修改缓存时间及缓存相关信息</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,abandon,retry:重试后端请求,重试计数器加1,当超过配置中max_retries值时会报错并进入vcl_backend_error子程序</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_backend_error子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">后端处理失败调用,异常页面展示效果处理,可自定义错误响应内容,或修改beresp.status与beresp.http.Location重定向等</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,retry</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_synth子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">自定义响应内容,可以通过synthetic()和返回值synth调用,这里可以自定义异常显示内容,也可以修改resp.status与resp.http.Location重定向</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:deliver,restart</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_init子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">加载vcl时最先调用,用于初始化VMODs,该子程序不参与请求处理,仅在vcl加载时调用一次</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:ok</td></tr></table><li><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold;color:blue"> <td width="200">vcl_fini子程序</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">卸载当前vcl配置时调用,用于清理VMODs,该子程序不参与请求处理,仅在vcl正常丢弃后调用</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold;color:grey"> <td width="200">返回值:ok</td></tr></table><br /><br /><li><p style="font-size:25px;font-weight:bold;color:green">后端服务器定义:</p><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">属性</td><td>说明</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.host= "IP";</td><td>要转向主机(即后端主机)的IP或域名,必填键值对</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.port = "80";</td><td>主机连接端口号或协议名(HTTP等),默认80</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.connect_timeout = 0.5s;</td><td>连接后端主机的超时时长</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.first_byte_timeout = 2s;</td><td>等待从后端返回的第一个字节时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.between_bytes_timeout = 2s;</td><td>每接收一个字节之间等待时间</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.probe = probe_name</td><td>监控后端主机的状态,指定外部监控name或者内部直接添加</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.max_connections = 1000;</td><td>设置最大并发连接数,超过这个数后连接就会失败</td></tr></table><li><p style="font-size:25px;font-weight:bold;color:green">监视器定义</p><table border="20" width="600" cellpadding="0" cellspacing="0"> <tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.url = "/";</td><td>指定监控入口地址,默认为“/”</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.request = "";</td><td>指定监控请求入口地址,比.url优先级高</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.timeout = "";</td><td>超时时长</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.window = "";</td><td>基于最近的多少次检查来判断其健康状态,默认为8</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.threshold = "";</td><td>最近.window中定义的这么次检查中至少有.threshold定义的次数是成功的,默认是3</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.interval = "";</td><td>检测频度,默认为5秒</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.initial = -1</td><td>window中有几次是良好启用此节点</td></tr><tr style="text-align:center;font-size:20px;font-weight:bold"> <td width="200">.expected_reponse = "";</td><td>期望的响应码,默认为200</td></tr></table><br /><li>检测实例:<pre>probe check { .url = "/"; .timeout = 2s; .interval = 2s; <code style="color:red;font-size:20px">//这里又引入了新的问题,虽然会去自动检测后端主机的健康性,但是后端主机会记录日志的,如果设定的时间过短,会增大后端服务器的磁盘压力,过长,则会使用户感觉不好,设一个稳点的值</code> .window = 8; .threshold = 6;}backend websrv { .host = "172.16.252.113"; .port = "80"; .max_connections = 500; .probe = check;}<code style="color:green">>backend.list</code>200 Backend name Refs Admin Probewebsrv(172.16.252.113,,80) 4 probe Sick 5/8 //检测出来的效果sick生病了default(127.0.0.1,,8080) 4 probe Healthy (no probe)backend.list200 Backend name Refs Admin Probewebsrv(172.16.252.113,,80) 4 probe Sick 4/8default(127.0.0.1,,8080) 4 probe Healthy (no probe)backend.list200 </pre><br /><br /><li><p style="font-size;20px;font-weight:bold;color:blue">PURGE和BAN操作,来清理特定的缓存,也可以在命令行中执行</p><pre>acl purgers { "127.0.0.1"; "192.168.0.0"/24;}sub vcl_recv { # allow PURGE from localhost and 192.168.0... if (req.method == "PURGE") { if (!client.ip ~ purgers) { return (synth(405, "Purging not allowed for " + client.ip)); } return (purge); }}sub vcl_purge { return (synth(200,"Purged,now!"));# set req.method = "GET";# return (restart);} if (req.method == "BAN") { if (!client.ip ~ purgers) { return (synth(405,"Banning not allowd for" + client.ip)); }<code style="color:red"> ban(" req.http.host == " + req.http.host + " && req.url == " + req.url); </code> //运算符边上必须有空格,要不然会实现不了功能的 return (synth(200,"Ban added.")); }操作:<code style="color:green">~]# varnish -S /etc/varnish/secret -T 127.0.0.1:6082</code>vcl.load test1 default.vclvcl.use test1 也可在此操作清除缓存:ban req.url ~ .js$ //清除以.js结尾的文件缓存,毕竟可以用正则表达式,多方便客户端操作:<code style="color:green">~]# crul -I http://172.16.254.35</code>HTTP/1.1 200 OKServer: nginx/1.10.2Date: Tue, 27 Jun 2017 09:27:38 GMTContent-Type: text/htmlContent-Length: 17Last-Modified: Tue, 27 Jun 2017 06:21:47 GMTETag: "5951f97b-11"X-Varnish: 3964978Age: 0Via: 1.1 varnish-v4X-Cache: Miss via172.16.254.35 //没有命中Connection: keep-alive<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>....X-Cache: Hit via172.16.254.35 //命中...进行PURGE操作:<code style="color:green">~]# curl -X PURGE http://172.16.254.35/index.html</code>...Error 405 Purging not allowed for172.16.251.81...再次访问:<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>...X-Cache: Miss via172.16.254.35 //不能命中缓存...<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>....X-Cache: Hit via172.16.254.35 //命中...进行BAN操作:<code style="color:green">~]# curl -X BAN http://172.16.254.35/index.html</code>...Error 405 Purging not allowed for172.16.251.81...再次访问:<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>...X-Cache: Miss via172.16.254.35 //不能命中缓存...<code style="color:green">~]# curl -I http://172.16.254.35/index.html</code>....X-Cache: Hit via172.16.254.35 //命中... </pre><br /><br /><li>实例:在缓存中,强制对某类资源的请求不检查缓存:<pre>vcl_recv { if (req.url ~ "(?i)^/(login|admin)") { //(?i)不区分字符大小写 return(pass); }} </pre><br /><li>实例:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;定义在vcl_backend_response中<pre>if (beresp.http.cache-control !~ "s-maxage") { //如果后端服务器没有给缓存时长 if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") { //同时匹配以.jpg...结尾的文件 unset beresp.http.Set-Cookie; <code style="color:red">//说明:默认情况下,varnish不缓存从后端响应的http头中带有Set-Cookie的对象。如果客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求递送至后端服务器上</code> set beresp.ttl = 3600s; //设置后端响应首部的生存时长为1h }}</pre><br /><li>实例:将真实的客户IP地址转移至后端服务器上,以便日志记录<pre>if (req.restarts == 0) { if (req.http.X-Fowarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip; } else { set req.http.X-Forwarded-For = client.ip; }}</pre><br /><br /><li>最后的一个整体笔记:<pre style="background:black;color:white;font-size:20px">import directors; <code style="color:red;font-size:20px">//负载均衡集群需要directors模块支持,import directors</code>acl purgers { <code style="color:red;font-size:20px">//对缓存资源进行控制</code> "127.0.0.1"; "172.16.0.0"/16;}probe check { <code style="color:red;font-size:20px">//对后端服务器的状态检测</code> .url = "/"; .timeout = 2s; .interval = 10s; .window = 8; .threshold = 6;}backend websrv { <code style="color:red;font-size:20px">//定义后端主机的属性</code> .host = "172.16.252.113"; .port = "80"; .max_connections = 500; .port = "80"; .max_connections = 500; .probe = check; <code style="color:red;font-size:20px">//执行健康状态检测</code>}backend websrv2 { .host = "172.16.250.84"; .port = "80"; .probe = check;}# Default backend definition. Set this to point to your content server.backend default { .host = "127.0.0.1"; .port = "8080";}sub vcl_init { <code style="color:red;font-size:20px">//初始化子程序创建后端主机组,即directors</code> new WEBGROUP = directors.round_robin(); <code style="color:red;font-size:20px">//使用new关键字创建director对象,使用round_robin算法</code> WEBGROUP.add_backend(websrv); WEBGROUP.add_backend(websrv2); WEBGROUP.add_backend(websrv); WEBGROUP.add_backend(websrv2);}sub vcl_recv { <code style="color:red;font-size:20px">//接受请求子程序</code> set req.backend_hint = WEBGROUP.backend(); <code style="color:red;font-size:20px">//调用后端主机组</code> if (req.url ~ "(?i)\.(JPG|PNG|GIF)") { <code style="color:red;font-size:20px">//对几种图片不进行缓存查找</code> return(pass); } if (req.restarts == 0) { <code style="color:red;font-size:20px">//IP地址转移</code> 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; } } if (req.method == "PURGE") { <code style="color:red;font-size:20px">//对某个缓存对象进行清理操作</code> if (!client.ip ~ purgers) { return (synth(405,"Purging not allowed for" + client.ip)); } return (purge); <code style="color:red;font-size:20px">//去往purge子程序操作</code> } if (req.method == "BAN") { <code style="color:red;font-size:20px">//清理某一类缓存对象</code> if (!client.ip ~ purgers) { return (synth(405,"Banning not allowd for" + client.ip)); } ban("req.http.host == " + req.http.host + " && req.url == " + req.url);<code style="color:red;font-size:20px">//清除host+url的对象</code> return (synth(200,"Ban added.")); }# if (req.url ~ "(?i)\.php$") { <code style="color:red;font-size:20px">//以.php请求至后端</code># set req.backend_hint = websrv;# } else {# set req.backend_hint = default;# }}sub vcl_purge { <code style="color:red;font-size:20px">//purge子程序</code> return (synth(200,"Purged"));<code style="color:red;font-size:20px">//合成信息,并返回值</code># set req.method = "GET";<code style="color:red;font-size:20px">//将请求方法设置成GET</code># return (restart);<code style="color:red;font-size:20px">//在发还给客户端,让客户端重新来取</code>}sub vcl_backend_response { # Happens after we have read the response headers from the backend. # # Here you clean the response headers, removing silly Set-Cookie headers # and other mistakes your backend does.}sub vcl_deliver { <code style="color:red;font-size:20px">//发送给客户的数据报文</code> if (obj.hits>0) { <code style="color:red;font-size:20px">//测试用,如果 有缓存,就把X-Cache首部信息发给客户端</code> set resp.http.X-Cache = "Hit via" + server.ip; } else { set resp.http.X-Cache = "Miss via" + server.ip; }}</pre><br /><br /><p style="font-size:25px;color:green">varnish日志区域:<br /><style type="text/css"> p{ text-indent:2em;} </style>1、varnishstat - Varnish Cache statistics<br /> <p> -1 //显示一次<br /></p><p> -1 -f FILED_NAME </p><p> -l:可用于-f选项指定的字段名称列表;</p> <p> MAIN.cache_hit </p><p> MAIN.cache_miss</p> <p> # varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss</p><p> # varnishstat -l -f MAIN -f MEMPOOL</p> <p> 2、varnishtop - Varnish log entry ranking</p><p> -1 Instead of a continously updated display, print the statistics once and exit.</p><p> -i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;</p><p> -I <[taglist:]regex></p><p> -x taglist:排除列表</p><p> -X <[taglist:]regex></p> <p> 3、varnishlog - Display Varnish logs</p> <p> 4、 varnishncsa - Display Varnish logs in Apache / NCSA combined log format</p></p><code style="font-size:20px;color:green">systemctl start varnishncsa.service //开启日志功能服务</code></ol></body></html>
阅读全文
0 0
- Varnish基础原理及简单配置
- varnish原理及配置
- varnish运行原理及配置
- Varnish的基础配置
- Varnish简单配置
- linux学习之rhel6.5 varnish服务简介及基础配置 应用
- varnish的安装与简单配置
- Varnish+Nginx 配置----Varnish
- linux下varnish安装及配置使用
- varnish配置
- Varnish配置
- varnish 配置
- DNS基础原理及配置详解
- Tomcat 基础配置及原理 (一)
- cacti远程监控原理及简单配置
- dubbo的简单配置及原理
- Varnish的简单配置与Drupal的集成
- 高性能HTTP加速器Varnish搭建、配置及优化
- Android重要知识点解析整理
- 机房重构-登陆
- 单片机字库建立
- 二叉树的路径和
- 算法笔记--二分/三分
- Varnish基础原理及简单配置
- PHP网络爬虫之CURL学习
- poj 3050 dfs(暴力)
- 最大流问题
- Python+Tornado+Nginx服务器部署解决方案
- Java数组相关,输入数字比大小,从小到大输出数组的值
- 数字货币开发专题(区块链概念是如何形成的)
- 几张图带你认识杭州的租房现状
- 背包问题