Varnish的VCL子程序

**

以下内容参考:

http://book.varnish-software.com/4.0/

**

VCL子进程,在其中定制Varnish的行为。VCL子例程可用于:添加自定义标头,更改Varnish错误消息的外观,在Varnish中添加HTTP重定向功能,清除内容以及定义缓存对象的哪些部分是唯一的。

注意:强烈建议尽可能让默认的内置子程序。内置子程序的设计考虑到安全性,这通常意味着它们可以合理的方式处理VCL代码中的任何缺陷。

vcl_recv

	规范化客户端输入
选择一个后端Web服务器
重新编写Web应用程序的客户端数据
根据客户端输入决定缓存策略
访问控制列表(ACL)
安全屏障,例如针对SQL注入攻击
修复错误,例如index.htlm- >index.html

vcl_recv是Varnish第一个VCL子进程,将客户端请求解析为其基本数据结构之后执行。 vcl_recv有四个主要用途:

	修改客户端数据以减少缓存的多样性。
决定使用哪个Web服务器。
根据客户端数据决定缓存策略。
执行特定Web应用程序所需的重写规则。

在vcl_recv你可以执行以下终止操作:

	pass:它通过缓存查找,但它执行Varnish请求流的其余部分。 pass不会将来自后端的响应存储在缓存中。
pipe:此操作创建一个全双工管道,将客户端请求转发到后端,且不查看其内容。后端回复被转发回客户端且不缓存其内容。由于Varnish不再尝试将内容映射到请求上,因此任何子进程的请求发送给活动连接将被通过pipe转发。pipe请求不会出现在任何日志中。
hash:它在缓存中查找请求。
purge:它在缓存中查找请求以便删除它。
synth -从Varnish生成合成响应。这种合成响应通常是一个带有错误信息的网页。 synth也可以用来重定向客户端请求。

同样可以使用vcl_recv来设置以下安全措施。varnish不是入侵检测系统的替代品,但仍可以用来提前阻止一些典型的攻击。简单访问控制列表(ACL)也可以应用到vcl_recv上。

内建的vcl_recv子进程不会缓存所有你想要的,同时也最好不要缓存错误内容而是把它们发送给错误的用户。

重新访问内置的vcl_recv:

	sub vcl_recv {
if (req.method == "PRI") {
/* We do not support SPDY or HTTP/2.0 */
return (synth(405));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
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);
}
return (hash);
}

示例:

	基本设备检测
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_pass

	进入pass模式是调用
sub vcl_pass {
return (fetch);
}

当上一层子进程返回pass动作后才会调用vcl_pass子进程。这动作的请求是在pass模式中设置的。vcl_pass通常作为一个重要的catch-all,服务于vcl_hit和vcl_miss执行结果。

vcl_pass可能会返回是三个动作:fetch、synth、或者是restart。当返回的的是fetch时,正在进行的请求就采用pass模式。采用pass模式从请求中抓取的对象不被缓存,但会传递到客户端。synth和restart返回的动作会调用相关的子进程。

hit-for-pass

		当一个对象不应该被缓存是使用
hit-for-pass对象取代抓取的对象
存在TTL
一些请求就不应该被缓存,一个典型的例子就是当一个请求页中含有set-cookie响应头部时,且 必须并只能把它递送给所需的客户端。因此你可以告诉varnish创建个hit-for-pass的对象并存储这个对象到缓存,而不是存储抓取的这个对象。分布式的请求被采用pass模式处理。
当一个对象不需要被缓存是,beresp.uncacheable变量会设置为true。结果,cacher进程会保持对hit-for-pass对象的hash散列应用。这种情况下,对请求的查找操作会传递给hash来找个hit-for-pass对象。如此类的请求会被vclpass子进程中的pass模式给处理。
如同其他缓存对象一样,hit-for-pass对象也有一个TTL(生命周期)。一旦生命周期过了,这个对象就会从缓存上删除。

vcl_backend_fetch

		sub vcl_backend_fetch {
return (fetch);
}
vcl_backend_fetch 可以从vcl_miss或vcl_pass中调用。当vcl_backend_fetch从vcl_miss中调用时,抓取的对象会被缓存。如果vcl_backend_fetch被从vcl_pass中调用时,抓取的对象也不会被缓存的,即使是obj.ttl或obj.keep变量的值比0大。
一个相关的变量是bereq.uncacheable,这个变量指示出从后端来的对象请求是否被缓存。当然从pass请求中来的对象是绝不被缓存的。
vcl_backend_fetch有俩个可能的终端操作,fetch或abandon。fetch动作发送请求给后动,abandon动作调用vcl_synth子进程。内建vcl_bakend_fetch子进程只返回fetch动作。
后端响应被vcl_backend-response还是vcl_backend_error处理取决于响应来之于那个服务。如果Varnish收到语法正确的HTTP响应,则Varnish将控制权交给vcl_backend_response。语法正确的HTTP响应包括HTTP 5xx错误代码。如果Varnish没有收到HTTP响应,则将控制权交给vcl_backend_error。

vcl_hash

	定义什么是唯一的请求
vcl_hash终是在vcl_recv后,或者另个子进程范围hash动作关键词。
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (lookup);
}

vcl_hash定义要用于缓存对象的hash key。Hash key将一个缓存对象与另一个缓存对象区分开来。默认的VCL为vcl_hash添加主机名或ip地址,同时添加请求的url给cache hash。

vcl_hash的一个用法是在cache hash上添加用户名来识别用户指定的数据。当然缓存用户数据时应该谨慎进行。一个更好的选择可能是hash每个会话缓存对象。

vcl_hash子进程返回lookup操作关键字。不像其他动作关键词,lookup是一个操作,而不是子进程。在vcl_hash后的下个状态取决于在缓存中lookup的查找。

当lookup操作没能匹配到任何hash时,它会创建一个带有busy标志的对象并存储在缓存中。然后,请求会被发送到vcl_miss子进程中。一旦请求被处理busy标志会被删除,并从后端的响应中更新对象。

随后遇到busy标记的对象请求将被发送到等待列表中。这个等待名单旨在提高响应性能,这个在waiting state 选项中有解释。

注意:一个高速缓存散列可以指代一个或多个对象变量。对象变量是基于Vary头域的创建的。在一个缓存散列下保留多个变量是比较好的做法,而不是每个变量创建一个散列。

vcl_hit

	在lookup操作之后执行,调用vcl_hash,找到(hits)在缓存上的对象。
sub vcl_hit {
if (obj.ttl >= 0s) {
// A pure unadultered hit, deliver it
return (deliver);
}
if (obj.ttl + obj.grace > 0s) {
// Object is in grace, deliver it
// Automatically triggers a background fetch
return (deliver);
}
// fetch & deliver once we get the result
return (fetch);
}

vcl_hit子进程通常通过调用含有deliver,restart或者synth的return()来进行终止。

如果对象的TTL+grace time没有过时的话,返回的deliver会控制vcl_deliver。如果过时时间超过了TTL,但没有超过TTL+grace time,deliver会调用与vcl_deliver同步的background fetch。background fetch是一种异步调用,用来插入一个新的请求对象到缓存中。grace time会在grace模式选项中有解释。

restart重启传输,并增加重启计数器设定值。如果重启的次数比max_restarts设定的值要大,varnish会发出一个guru mediation的错误。

synth(status code,reason)返回指定状态码给客户端并丢弃请求。

vcl_miss

	如果一个请求对象没有被lookup操作找到时子进程会被调用。
包含有是否尝试从后端检索文档以及使用那个后端的策略。
sub vcl_miss {
return (fetch);
}

子进程vcl_hit和vcl_miss是相关的。你很少调用他们,因为HTTP请求投吧的修改通常是在vcl_recv中进行。但是,如果你不希望发送X-Varnish头部给后端服务,你可以把它移动动vcl_miss或vcl_pass中。基于这种情况,你可以使用unset bereq ,http,x-varnish。

vcl_deliver

	所有请求流程的公共最后退出点,除了通过vcl_pipe的请求。
经常用于添加和移除debug-headers。
sub vcl_deliver {
return (deliver);
}

vcl_deliver子进程是简单的,同样也是对修改varnish的输出很有用的。如果你需要删除一个头部,或添加一个不应该存储在cache中的头部,vcl_deliver可以胜任这个工作。

在vcl_deliver中常用的且被可被修改的变量是:

	resp.http.*:发送个客户端的头部,它们可以被set和unset。
resp.status:状态码为200,404,503等
resp.reason:被返回给客户端的http状态信息
obj.hit:在对象上的cache-hits的数。因此,0代表miss,可以评估这个变量来轻松地显示响应是来自缓存命中还是未命中。
req.restarts:在VCL中发出的重启次数 - 如果没有发生,则返回0。

vcl_synth

	用于在Varnish中生成内容
错误消息可以在这里创建
其他用例:重定向用户(301/302重定向)

vcl/default-vcl_synth.vcl:

	sub vcl_synth {
set resp.http.Content-Type = "text/html; charset=utf-8";
set resp.http.Retry-After = "5";
synthetic( {"<!DOCTYPE html>
<html>
<head>
<title>"} + resp.status + " " + resp.reason + {"</title>
</head>
<body>
<h1>Error "} + resp.status + " " + resp.reason + {"</h1>
<p>"} + resp.reason + {"</p>
<h3>Guru Meditation:</h3>
<p>XID: "} + req.xid + {"</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
"} );
return (deliver);
}

你可以创建合成响应,例如,在vcl_synth上的个性化错误信息。调用这个子进程你可以做:

return (synth(status_code, "reason"));

注意synth不是一个关键字,而是个带有参数的函数。

你必须为vcl_synth明确地返回status code和reason参数。在resp.http上设置合成响应的头部。

注意:从 vcl/default-vcl_synth.vcl注意到 {" and "}可以用于创建多行的字段。这个不仅限于synthetic()函数,在其他地址也可以使用。vcl_synth定义的对象绝不在缓存上存储,对立与vcl_backend_error定义的对象。

示例:

	使用vcl_synth重定向请求
sub vcl_recv {
if (req.http.host == "www.example.com") {
set req.http.location = "http://example.com" + req.url;
return (synth(750, "Permanently moved"));
}
}
sub vcl_synth {
if (resp.status == 750) {
set resp.http.location = req.http.location; set resp.status = 301;
return (deliver); }
}

Varnish的vcl子程序的更多相关文章

  1. Varnish的VCL

    Varnish的子进程 VCL Varnish配置语言VCL是一种"域"专有类型的配置语言,用于描述Varnish Cache的请求处理和文档高速缓存策略. 当加载新配置时,Man ...

  2. 01 . Varnish简介,原理,配置缓存

    简介 Varnish是高性能开源的反向代理服务器和HTTP缓存服务器,其功能与Squid服务器相似,都可以用来做HTTP缓存.可以安装 varnish 在任何web前端,同时配置它缓存内容.与传统的 ...

  3. 关于varnish缓存

    目录 缓存的概念 一.varnish缓存 1. 简介 2. 总体结构 2.1 两个主进程 2.1.1 Management进程 2.1.2 Child/Cacher进程 2.2 Varnish的日志收 ...

  4. 利用varnish做Discuz论坛的缓存服务器

    实验背景:公司有一台BBS服务器,用的是LNMP的架构搭建的.正好手头有一台空闲的虚拟机,于是想着给BBS前端加一台缓存服务器.于是选定了varnish,搜了很多教程,跌跌撞撞的完成了配置.这其中很多 ...

  5. varnish4.1 配置文件default.vcl

    varnish4.1 配置文件default.vcl # This .x VCL file vcl 4.0; backend default { .host = "127.0.0.1&quo ...

  6. Varnish常用相关命令工具

    varnishd启动./varnishd  -f /usr/local/varnish-3.0.2/etc/varnish/default.vcl -s malloc,1G -T 127.0.0.1: ...

  7. 学习varnish随笔

    Varnish是一款高性能.开源的反向代理服务器和缓存服务器.Varnish使用内存缓存文件来减少响应时间和网络带宽消耗.这个项目是由挪威的一家报纸Verdens Gang的网络分支起始的,其架构设计 ...

  8. varnish

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  9. Nginx+Varnish 实现动静分离,为服务器分流,降低服务器负载

    相必大家在看加快网站响应速度方面的文章时,都提过这么一条:动静分离.那怎样实现动静分离呢,这里笔者就亲自搭建相关服务实现动静分离. 动静分离是一种架构,就是把静态文件,比如JS.CSS.图片甚至有些静 ...

随机推荐

  1. Word+PS制作拼音表格

    这几天,朋友让帮忙做个拼音表格,使用Word可以直接标注音标,却无法实现小时候那种4线3格,Word的模板只有练习书法的.使用Excel却,无法将拼音标注单独标注到上一单元格(有朋友会VBA的话,帮我 ...

  2. ubuntu更换阿里源

    网上应该可以找到很多关于ubuntu源的设置方法,但是如果不搞清楚就随便设置的话,不仅不能起到应有的效果,还会由于一些问题导致apt不可用. 最正确的更换源的方法应该如系统提示的: ## a.) ad ...

  3. 第一章:大数据 の Linux 基础 [更新中]

    本课主题 Linux 休系结构图 Linux 系统启动的顺序 Linux 查看内存和 CPU 指令 环境变量加载顺序 Linux 内存结构 Linux 休系结构图 Linux 大致分为三个层次,第一层 ...

  4. MyEclipse过期后怎么破解

    方法一:写一个程序生成Subscriptioncode import java.io.*; public class MyEclipseGen { private static final Strin ...

  5. unisound_asr 云知声 语音识别 python版接口

    抽空,实现了一份云知声 语音转写的python版本. 使用python通过调用动态库实现. 云知声官网: http://dev.hivoice.cn/sdk_download/schema_sdk.j ...

  6. Chris Richardson微服务翻译:微服务架构中的服务发现

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现(本文) 微服务之事件驱动的数据管理 微服 ...

  7. Adobe Acrobat pro生成PDF模版

    最近做了一个关于动态生成PDF合同的需求  java生成PDF 网络上随便一搜遍有了 不要用手动在代码里面输入合同中的文字这种方式 如这样的方式 http://blog.csdn.net/justin ...

  8. org.springframework.data.redis.serializer.SerializationException: Cannot serialize;

    前言 本文中提到的解决方案,源码地址在:perfect-ssm,希望可以帮你解决问题. 问题描述 在Spring与Redis整合过程中,出现了如下报错: org.springframework.dat ...

  9. Redis 数据结构与内存管理策略(上)

    Redis 数据结构与内存管理策略(上) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 Redis 数据类型特点与使用场景 String.Li ...

  10. HDU 1166 敌兵布阵(线段树单点更新,板子题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...