Varnish缓存服务器详解
1、VCL状态引擎 在VCL状态引擎中状态之间具有相关性但彼此间互相隔离每个引擎使用return(x)来退出当前状态并指示varnish进入下一个状态,因此在某个时刻至少有thread_pool_min*thread_pools个worker线程在运行但至多不能超出thread_pool_max*thread_pools个。
不同的director可以使用同一个后端主机而某director也可以使用“匿名”后端主机(在director中直接进行定义)。
4、Banning ban()是一种从已缓存对象中过滤(filter)出某此特定的对象并将其移除的缓存内容刷新机制不过它并不阻止新的内容进入缓存或响应于请求, varnish开始处理一个请求时首先需要分析HTTP请求本身比如从首部获取请求方法、验正其是否为一个合法的HTT请求等,sub)这两个用于基于正则表达式搜索指定的字符串并将其替换为指定的字符串但regsuball()可以将str中能够被regex匹配到的字符串统统替换为subregsub()只替换一次 ban(expression) ban_url(regex)Bans所有其URL能够由regex匹配的缓存对象 purge从缓存中挑选出某对象以及其相关变种一并删除这可以通过HTTP协议的PURGE方法完成 hash_data(str) return()当某VCL域运行结束时将控制权返回给Varnish并指示Varnish如何进行后续的动作其可以返回的指令包括lookup、pass、pipe、hit_for_pass、fetch、deliver和hash等但某特定域可能仅能返回某些特定的指令而非前面列出的全部指令 return(restart)重新运行整个VCL即重新从vcl_recv开始进行处理每一次重启都会增加req.restarts变量中的值而max_restarts参数则用于限定最大重启次数,缓存中的所有对象在响应给客户端之前都会被ban列表检查至少一次检查完成后将会为每个缓存创建一个指向与其匹配的ban语句的指针,size[,下面是线程池相关的各参数及其配置 thread_pool_add_delay 2 [milliseconds] thread_pool_add_threshold 2 [requests] thread_pool_fail_delay 200 [milliseconds] thread_pool_max 500 [threads] thread_pool_min 5 [threads] thread_pool_purge_delay 1000 [milliseconds] thread_pool_stack 65536 [bytes] thread_pool_timeout 120 [seconds] thread_pool_workspace 16384 [bytes] thread_pools 2 [pools] thread_stats_rate 10 [requests] 其中最关键的当属thread_pool_max和thread_pool_min它们分别用于定义每个线程池中的最大线程数和最少线程数, 5、vcl_fetch 如前面所述相对于vcl_recv是根据客户端的请求作出缓存决策来说vcl_fetch则是根据服务器端的响应作出缓存决策, 4、vcl_recv vcl_recv是在Varnish完成对请求报文的解码为基本数据结构后第一个要执行的子例程它通常有四个主要用途 (1)修改客户端数据以减少缓存对象差异性比如删除URL中的等字符 (2)基于客户端数据选用缓存策略比如仅缓存特定的URL请求、不缓存POST请求等 (3)为某web应用程序执行URL重写规则 (4)挑选合适的后端Web服务器 可以使用下面的终止语句即通过return()向Varnish返回的指示操作 pass绕过缓存即不从缓存中查询内容或不将内容存储至缓存中 pipe不对客户端进行检查或做出任何操作而是在客户端与后端服务器之间建立专用“管道”并直接将数据在二者之间进行传送此时keep-alive连接中后续传送的数据也都将通过此管道进行直接传送并不会出现在任何日志中 lookup在缓存中查找用户请求的对象如果缓存中没有其请求的对象后续操作很可能会将其请求的对象进行缓存 error由Varnish自己合成一个响应报文一般是响应一个错误类信息、重定向类信息或负载均衡器返回的后端web服务器健康状态检查类信息 vcl_recv也可以通过精巧的策略完成一定意义上的安全功能以将某些特定的攻击扼杀于摇篮中,client类型的director使用client.identity作为挑选因子这意味着client.identity相同的请求都将被发送至同一个后端主机, 五、修剪缓存对象 1、缓存内容修剪 提高缓存命中率的最有效途径之一是增加缓存对象的生存时间(TTL)但是这也可能会带来副作用比如缓存的内容在到达为其指定的有效期之间已经失效, sub) regsub($req.url,默认线程池的数量为2这对最繁忙的varnish服务器来说也已经足够, Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等, regsub(str, 这里需要特殊说明的是Varnish 2中的purge()操作在Varnish 3中被替换为了ban()操作而Varnish 3也使用了purge操作但为其赋予了新的功能且只能用于vcl_hit或vcl_miss中替换Varnish 2中常用的set obj.ttl0s, 六、Varnish检测后端主机的健康状态 Varnish可以检测后端主机的健康状态在判定后端主机失效时能自动将其从可用后端主机列表中移除而一旦其重新变得可用还可以自动将其设定为可用, request response Cache-Control Cache-Control : 1#cache-directive cache-directive cache-request-directive | cache-response-directive cache-request-directive no-cache | no-store (backup) | max-age delta-seconds | max-stale [ delta-seconds ] | min-fresh delta-seconds | no-transform | only-if-cached | cache-extension cache-response-directive public | private [ 1#field-name ] | no-cache [ 1#field-name ] | no-store | no-transform | must-revalidate | proxy-revalidate | max-age delta-seconds | s-maxage delta-seconds | cache-extension sub vcl_deliver { set resp.http.X-Age resp.http.Age; unset resp.http.Age; if (obj.hits 0) { set resp.http.X-Cache “HIT”; } else { set resp.http.X-Cache “MISS”; } } acl purgers { “127.0.0.1”; “192.168.0.0”/24; } sub vcl_recv { if (req.request “PURGE”) { if (!client.ip ~ purgers) { error 405 “Method not allowed”; } return (lookup); } } sub vcl_hit { if (req.request “PURGE”) { purge; error 200 “Purged”; } } sub vcl_miss { if (req.request “PURGE”) { purge; error 404 “Not in cache”; } } sub vcl_pass { if (req.request “PURGE”) { error 502 “PURGE on a passed object”; } } sed /pattern/string/g 在请求的时候使用curl -H PURGE URL regsub(str, backend web1 { .host backweb1.magedu.com; .port 80; } director webservers random { .retries 5; { .backend web1; .weight 2; } { .backend { .host backweb2.magedu.com; .port 80; } .weight 3; } } 如上示例中web1为显式定义的后端主机而webservers这个directors还包含了一个“匿名”后端主机(backweb2.magedu.com),编译后的旧版本配置通常在varnish重启时才会被丢弃如果需要手动清理则可以使用varnishadm的vcl.discard命令完成, 3、线程模型(Trheading model) varnish的child进程由多种不同的线程组成分别用于完成不同的工作,然而需要注意的是varnishd实际上使用的空间比使用-s选项指定的缓存空间更大一般说来其需要为每个缓存对象多使用差不多1K左右的存储空间这意味着对于100万个缓存对象的场景来说其使用的缓存空间将超出指定大小1G左右,如果没有指向ban列表的首部其将对使用所有的新添加的ban语句对此缓存对象进行测试如果没有任何ban语句能够匹配则更新ban列表,VCL的return语句用于将控制权从VCL状态引擎返回给Varnish而非默认函数这就是为什么VCL只有终止语句而没有返回值的原因,size] 或 file[, sub) regsuball(str,而为了减少竞争每个worker线程都使用了日志数据缓存,如果管理员没有自定义vcl_recv函数varnish将会执行默认的vcl_recv函数,根据需要这两个参数的数量可以进行调整varnishstat命令的n_wrk_queued可以显示当前varnish的线程数量是否足够如果队列中始终有不少的线程等待运行则可以适当调大thread_pool_max参数的值。
regex,其基本语法说明如下 (1)//、#或/* comment */用于注释 (2)sub $name 定义函数 (3)不支持循环有内置变量 (4)使用终止语句没有返回值 (5)域专用 (6)操作符(赋值)、(等值比较)、~(模式匹配)、!(取反)、(逻辑与)、||(逻辑或) VCL的函数不接受参数并且没有返回值因此其并非真正意义上的函数这也限定了VCL内部的数据传递只能隐藏在HTTP首部内部进行, 3、VCL Varnish Configuration Language (VCL)是varnish配置缓存策略的工具它是一种基于“域”(domain specific)的简单编程语言它支持有限的算术运算和逻辑运算操作、允许使用正则表达式进行字符串匹配、允许用户使用set自定义变量、支持if判断语句也有内置的函数和变量等,因此更好的办法是在VCL规则中判断req.backend.healthy变量显示某后端主机不可用时为此后端主机增大req.grace变量的值以设定适用的宽容期限长度,其实现方法本处不再详细说明, 2、varnish日志 为了与系统的其它部分进行交互Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log)因此如果某线程需要记录信息其仅需要持有一个锁而后向共享内存中的某内存区域写入数据再释放持有的锁即可,client.identity默认为cliet.ip但也可以在VCL中将其修改为所需要的标识符,然而除非特别需要对其进行修改保持这些参数为默认值可以有效降低管理复杂度,varnish内部有几个所谓的状态(state)在这些状态上可以附加通过VCL定义的策略以完成相应的缓存处理机制因此VCL也经常被称作“域专用”语言或状态引擎“域专用”指的是有些数据仅出现于特定的状态中,size {experimental} file中的granularity用于设定缓存空间分配单位默认单位是字节所有其它的大小都会被圆整。
选择使用合适的存储方式有助于提升系统性从经验的角度来看建议在内存空间足以存储所有的缓存对象时使用malloc的方法反之file存储将有着更好的性能的表现,varnish以轮转(round-robin)的方式使用其存储空间,此时可以通过启动脚本使用-p选项在varnishd启动时为其设定参数的值,使用VCL编写的缓存策略通常保存至.vcl文件中其需要编译成二进制的格式后才能由varnish调用,反对意见主要有两种一是ban不会释放内存缓存对象仅在有客户端访问时被测试一次二是如果缓存对象曾经被访问到但却很少被再次访问时ban列表将会变得非常大, 4、varnish的后端存储 varnish支持多种不同类型的后端存储这可以在varnishd启动时使用-s选项指定,ban本身就是一个或多个VCL风格的语句它会在Varnish从缓存哈希(cache hash)中查找某缓存对象时对搜寻的对象进行比较测试因此一个ban语句就是类似匹配所有“以/downloads开头的URL”或“响应首部中包含nginx的对象”,同时对于每个“域”来说可以定义一个或多个终止语句以告诉Varnish下一步采取何种操作如查询缓存或不查询缓存等,与此同时线程池的数量也只能在流量较大的场景下才需要增加而且经验表明其多于2个对提升性能并无益处, 5、 九、Varnish的命令行工具 1、varnishadm命令 命令语法varnishadm [-t timeout] [-S secret_file] [-T address:port] [-n name] [command [...]] 通过命令行的方式连接至varnishd进行管理操作的工具指定要连接的varnish实例的方法有两种 -n name —— 连接至名称为“name”的实例 -T address:port —— 连接至指定套接字上的实例 其运行模式有两种当不在命令行中给出要执行的command时其将进入交互式模式否则varnishadm将执行指定的command并退出,granularity]]] 或 persistent, regex, Varnish的director支持的挑选方法中比较简单的有round-robin和random两种,使用purge会移除旧的缓存对象但如果上游服务器宕机而无法取得新版本的内容时此内容将无法再响应给客户端,此时如果上游服务器宕机或未响应旧的内容将保持原状并能够继续服务于那些未使用req.has_always_misstrue的客户端直到其过期失效或由其它方法移除,要查看本地启用的缓存可使用如下命令进行, # varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 storage.list sub vcl_deliver { if (obj.hits 0) { set resp.http.X-Cache HIT; } else { set resp.http.X-Cache MISS; } } sub vcl_deliver { if (obj.hits 0) { set resp.http.X-Cache HIT via server.hostname; } else { set resp.http.X-Cache MISS via server.hostname; } } sub vcl_recv { if (req.url ~ ^/test.html$) { return(pass); } } sub vcl_fetch { if (req.request GET req.url ~ \.(html|jpg|jpeg)$) { set beresp.ttl 3600s; } } sub vcl_fetch { if (beresp.http.cache-control !~ s-maxage) { if (req.url ~ \.jpg(\?|$)) { set beresp.ttl 30s; unset beresp.http.Set-Cookie; } if (req.url ~ \.html(\?|$)) { set beresp.ttl 10s; unset beresp.http.Set-Cookie; } } else { if (beresp.ttl 0s) { unset beresp.http.Set-Cookie; } } } sub vcl_error { synthetic htmlbody!-- Something was wrong! --/body/html; set obj.status 200; return (deliver); } 1.1,因此varnish修改配置的开销非常小其可以同时保有几份尚在引用的旧版本配置也能够让新的配置即刻生效,。
regex, sub) ban_url(regex) ban(expression) purge; return(restart) return() hash_data() 子例程 vcl_recv { } cookie # Drop any cookies sent to Wordpress. sub vcl_recv { if (!(req.url ~ wp-(login|admin))) { unset req.http.cookie; } } # Drop any cookies Wordpress tries to send back to the client. sub vcl_fetch { if (!(req.url ~ wp-(login|admin))) { unset beresp.http.set-cookie; } } ,其中round-robin类型没有任何参数只需要为其指定各后端主机即可挑选方式为“轮叫”并在某后端主机故障时不再将其视作挑选对象random方法随机从可用后端主机中进行挑选每一个后端主机都需要一个.weight参数以指定其权重同时还可以director级别使用.retires参数来设定查找一个健康后端主机时的尝试次数。
另外为了保存数据结构等varnish自身也会占去不小的内存空间,在Varnish中ban的实现是指将一个ban添加至ban列表(ban-list)中这可以通过命令行接口或VCL实现它们的使用语法是相同的,使用req.has_always_missture可以让Varnish在缓存中搜寻相应的内容但却总是回应“未命中”于是vcl_miss将后续地负责启动vcl_fetch从上游服务器取得新内容并以新内容缓存覆盖旧内容,HTTP协议的PURGE方法可以实现purge功能不过其仅能用于vcl_hit和vcl_miss中它会释放内存工作并移除指定缓存对象的所有Vary:-变种并等待下一个针对此内容的客户端请求到达时刷新此内容,这个决定的实现则需要由VCL来完成简单来说要由vcl_recv方法来完成,另外其一般要与return(restart)一起使用, Varnish 2.1.0后random挑选方法又多了两种变化形式client和hash,在任何VCL状态引擎中返回的pass操作都将由vcl_fetch进行后续处理。
二、安装varnish 三、HTTP协议与varnish 1、缓存相关的HTTP首部 HTTP协议提供了多个首部用以实现页面缓存及缓存失效的相关功能这其中最常用的有 (1)Expires用于指定某web对象的过期日期/时间通常为GMT格式一般不应该将此设定的未来过长的时间一年的长度对大多场景来说足矣其常用于为纯静态内容如JavaScripts样式表或图片指定缓存周期 (2)Cache-Control用于定义所有的缓存机制都必须遵循的缓存指示这些指示是一些特定的指令包括public、private、no-cache(表示可以存储但在重新验正其有效性之前不能用于响应客户端请求)、no-store、max-age、s-maxage以及must-revalidate等Cache-Control中设定的时间会覆盖Expires中指定的时间 (3)Etag响应首部用于在响应报文中为某web资源定义版本标识符 (4)Last-Mofified响应首部用于回应客户端关于Last-Modified-Since或If-None-Match首部的请求以通知客户端其请求的web对象最近的修改时间 (5)If-Modified-Since条件式请求首部如果在此首部指定的时间后其请求的web内容发生了更改则服务器响应更改后的内容否则则响应304(not modified) (6)If-None-Match条件式请求首部web服务器为某web内容定义了Etag首部客户端请求时能获取并保存这个首部的值(即标签)而后在后续的请求中会通过If-None-Match首部附加其认可的标签列表并让服务器端检验其原始内容是否有可以与此列表中的某标签匹配的标签如果有则响应304否则则返回原始内容 (7)Vary响应首部原始服务器根据请求来源的不同响应的可能会有所不同的首部最常用的是Vary: Accept-Encoding用于通知缓存机制其内容看起来可能不同于用户请求时Accept-Encoding-header首部标识的编码格式 (8)Age缓存服务器可以发送的一个额外的响应首部用于指定响应的有效期限浏览器通常根据此首部决定内容的缓存时长如果响应报文首部还使用了max-age指令那么缓存的有效时长为“max-age减去Age”的结果 四、Varnish状态引擎(state engine) VCL用于让管理员定义缓存策略而定义好的策略将由varnish的management进程分析、转换成C代码、编译成二进制程序并连接至child进程,类似地hash类型的director使用hash数据作为挑选因子这意味着对同一个URL的请求将被发往同一个后端主机其常用于多级缓存的场景中, Varnish默认的vcl_recv专门设计用来实现安全的缓存策略它主要完成两种功能 (1)仅处理可以识别的HTTP方法并且只缓存GET和HEAD方法 (2)不缓存任何用户特有的数据 安全起见一般在自定义的vcl_recv中不要使用return()终止语句而是再由默认vcl_recv进行处理并由其做出相应的处理决策,例如 cache-worker线程每连接一个用于处理请求 cache-main线程全局只有一个用于启动cache ban lurker线程一个用于清理bans acceptor线程一个用于接收新的连接请求 epoll/kqueue线程数量可配置默认为2用于管理线程池 expire线程一个用于移除老化的内容 backend poll线程每个后端服务器一个用于检测后端服务器的健康状况 在配置varnish时一般只需为关注cache-worker线程而且也只能配置其线程池的数量而除此之外的其它均非可配置参数, 为varnishd指定使用的缓存类型时-s选项可接受的参数格式如下 malloc[。
acl purgers { 127.0.0.1; 192.168.0.0/24; } sub vcl_recv { if (req.request PURGE) { if (!client.ip ~ purgers) { error 405 Method not allowed; } return (lookup); } } sub vcl_hit { if (req.request PURGE) { purge; error 200 Purged; } } sub vcl_miss { if (req.request PURGE) { purge; error 404 Not in cache; } } sub vcl_pass { if (req.request PURGE) { error 502 PURGE on a passed object; } } 客户端在发起HTTP请求时只需要为所请求的URL使用PURGE方法即可其命令使用方式如下 # curl -I PURGE 3、强制缓存未命中 在vcl_recv中使用return(pass)能够强制到上游服务器取得请求的内容但这也会导致无法将其缓存,webservers从这两个后端主机中挑选一个主机的方法为random即以随机方式挑选, 2、共享内存日志 共享内存日志(shared memory log)通常被简称为shm-log它用于记录日志相关的数据大小为80M,当这些基本分析结束后就需要做出第一个决策即varnish是否从缓存中查找请求的资源,正是由于编译工作在child进程之外完成它避免了装载错误格式VCL的风险,Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行如果在指定的时长内未得到Child进程的回应Management将会重启此Child进程,sub) regsuball(str,path[。
七、Varnish使用多台后端主机 Varnish中可以使用director指令将一个或多个近似的后端主机定义为一个逻辑组并可以指定的调度方式(也叫挑选方法)来轮流将请求发送至这些主机上,同时它也可以检查出一些拼写类的错误并将其进行修正等,而persistent方法的出现对此有了一个弥补但persistent仍处于测试阶段例如目前尚无法有效处理要缓存对象总体大小超出缓存空间的情况所以其仅适用于有着巨大缓存空间的场景。
但一般建议每台varnish服务器上最多运行的worker线程数不要超出5000个,一般不需要对shm-log做出更多的设定但应该避免其产生I/O这可以使用tmpfs实现其方法为在/etc/fstab中设定一个挂载至/var/lib/varnish目录(或其它自定义的位置)临时文件系统即可, Child进程包含多种类型的线程常见的如 Acceptor线程接收新的连接请求并响应 Worker线程child进程会为每个会话启动一个worker线程因此在高并发的场景中可能会出现数百个worker线程甚至更多 Expiry线程从缓存中清理过期内容 Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性。
编译完成后management负责将其连接至varnish实例即child进程, backend web1 { .host ; .probe { .url /.healthtest.html; .interval 1s; .window 5; .threshold 2; } } .probe中的探测指令常用的有 (1) .url探测后端主机健康状态时请求的URL默认为“/” (2) .request: 探测后端主机健康状态时所请求内容的详细格式定义后它会替换.url指定的探测方式比如 .request GET /.healthtest.html HTTP/1.1 Host: Connection: close; (3) .window设定在判定后端主机健康状态时基于最近多少次的探测进行默认是8 (4) .threshold在.window中指定的次数中至少有多少次是成功的才判定后端主机正健康运行默认是3 (5) .initialVarnish启动时对后端主机至少需要多少次的成功探测默认同.threshold (6) .expected_response期望后端主机响应的状态码默认为200 (7) .interval探测请求的发送周期默认为5秒 (8) .timeout每次探测请求的过期时长默认为2秒 因此如上示例中表示每隔1秒对此后端主机探测一次请求的URL为在最近5次的探测请求中至少有2次是成功的(响应码为200)就判定此后端主机为正常工作状态,赞成的意见则主要集中在ban可以让Varnish在恒定的时间内完成向ban列表添加ban的操作例如在有着数百万个缓存对象的场景中添加一个ban也只需要在恒定的时间内即可完成,然而无论是client还hash当其倾向于使用后端主机不可用时将会重新挑选新的后端其机, 3、VCL的内置函数 VCL提供了几个函数来实现字符串的修改添加bans重启VCL状态引擎以及将控制权转回Varnish等,path, 八、varnish管理进阶 1、可调参数 Varnish有许多参数虽然大多数场景中这些参数的默认值都可以工作得很好然而特定的工作场景中要想有着更好的性能的表现则需要调整某些参数,Varnish在从缓存中获取对象时总是会检查此缓存对象的指针是否指向了ban列表的首部。
下面是个在VCL中配置的示例,在varnish内部有多种不同的工作区其中最关键的当属用于管理会话数据的session工作区, 一、关于Varnish 1、varnish系统架构 varnish主要运行两个进程Management进程和Child进程(也叫Cache进程)。
每个director都必须有其专用名且在定义后必须在VCL中进行调用VCL中任何可以指定后端主机的位置均可以按需将其替换为调用某已定义的director, ) purge: 让缓存失效的 ban() URL rewrite VCL - functions regsub(str, 当某连接请求到达时varnish选择一个线程池负责处理此请求, www\.maged\.com, 在具体执行某清理工作时需要事先确定如下问题 (1)仅需要检验一个特定的缓存对象还是多个 (2)目的是释放内存空间还是仅替换缓存的内容 (3)是不是需要很长时间才能完成内容替换 (4)这类操作是个日常工作还是仅此一次的特殊需求 2、移除单个缓存对象 purge用于清理缓存中的某特定对象及其变种(variants)因此在有着明确要修剪的缓存对象时可以使用此种方式, 2、VCL语法 VCL的设计参考了C和Perl语言因此对有着C或Perl编程经验者来说其非常易于理解,通过return()返回给arnish的操作指示有 (1)deliver缓存此对象并将其发送给客户端(经由vcl_deliver) (2)hit_for_pass不缓存此对象但可以导致后续对此对象的请求直接送达到vcl_pass进行处理 (3)restart重启整个VCL并增加重启计数超出max_restarts限定的最大重启次数后将会返回错误信息 (4)error code [reason]返回指定的错误代码给客户端并丢弃此请求 默认的vcl_fetch放弃了缓存任何使用了Set-Cookie首部的响应,然而在命令行接口中进行的修改不会保存至任何位置因此重启varnish后这些设定会消失,varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示, regex,事实上整个缓存策略就是由几个特定的子例程如vcl_recv、vcl_fetch等组成它们分别在不同的位置(或时间)执行如果没有事先为某个位置自定义子例程varnish将会执行默认的定义,为了避免误判Varnish在探测后端主机的健康状态发生转变时(比如某次探测时某后端主机突然成为不可用状态)通常需要连续执行几次探测均为新状态才将其标记为转换后的状态,例如 ban req.http.host magedu.com req.url ~ \.gif$ 定义好的所有ban语句会生成一个ban列表(ban-list)新添加的ban语句会被放置在列表的首部,然而即便管理员自定义了vcl_recv但如果没有为自定义的vcl_recv函数指定其终止操作(terminating)其仍将执行默认的vcl_recv函数。
regex, 如果Varnish在某时刻没有任何可用的后端主机它将尝试使用缓存对象的“宽容副本”(graced copy)当然此时VCL中的各种规则依然有效,因此手动检验缓存对象的有效性或者刷新缓存是缓存很有可能成为服务器管理员的日常工作之一相应地Varnish为完成这类的任务提供了三种途径HTTP 修剪(HTTP purging)、禁用某类缓存对象(banning)和强制缓存未命令(forced cache misses)。
后端存储的类型包括 (1)file使用特定的文件存储全部的缓存数据并通过操作系统的mmap()系统调用将整个缓存文件映射至内存区域(如果条件允许) (2)malloc使用malloc()库调用在varnish启动时向操作系统申请指定大小的内存空间以存储缓存对象 (3)persistent(experimental)与file的功能相同但可以持久存储数据(即重启varnish数据时不会被清除)仍处于测试期 varnish无法追踪某缓存对象是否存入了缓存文件从而也就无从得知磁盘上的缓存文件是否可用因此file存储方法在varnish停止或重启时会清除数据,vcl_fetch中有许多可用的内置变量比如最常用的用于定义某对象缓存时长的beresp.ttl变量, VCL策略在启用前会由management进程将其转换为C代码而后再由gcc编译器将C代码编译成二进制程序,可以在管理接口中使用param.show命令查看这些参数而使用param.set则能修改这些参数的值, 下面是一个自定义的使用示例 sub vcl_recv { if (req.http.User-Agent ~ iPad || req.http.User-Agent ~ iPhone || req.http.User-Agent ~ Android) { set req.http.X-Device mobile; } else { set req.http.X-Device desktop; } } 此例中的VCL创建一个X-Device请求首部其值可能为mobile或desktop于是web服务器可以基于此完成不同类型的响应以提高用户体验, 共享内存日志大小一般为90M其分为两部分前一部分为计数器后半部分为客户端请求的数据,而如果此线程池中的线程数量已经达到最大值新的请求将会被放置于队列中或被直接丢弃。
每个后端服务器当前探测的健康状态探测方法通过.probe进行设定其结果可由req.backend.healthy变量获取也可通过varnishlog中的Backend_health查看或varnishadm的debug.health查看, 4、线程相关的参数(Threading parameters) varnish为每个连接使用一个线程因此其worker线程的最大数决定了varnish的并发响应能力,事实上varnish官方强烈建议让varnish执行默认的vcl_recv以便处理自定义vcl_recv函数中的可能出现的漏洞, 对ban这种实现方式持反对意见有有之持赞成意见者亦有之。
评论列表