最近要使用varnish 4 但竟然百度、必应(没×××谷歌)都找不到靠谱的配置文件 只能忍痛看了几天官方文档 现在把成果分享一下

# 使用varnish版本4的格式.

vcl 4.0;

# 加载后端轮询模块

import directors;

#######################健康检查策略区域###########################

# 名为www_probe的健康检查策略

probe www_probe {

.request =

"GET /html/test.html HTTP/1.1"    # 健康检查url为/html/test.html 协议为http1.1

"Host: www.xxxxx.com"        # 访问的域名为www.xxxxx.com

"Connection: close";        # 检查完关闭连接

#其他参数 如 超时时间 检查间隔 等 均使用默认

}

##################################################################

#######################配置后端区域################################

backend backend_16 {

.host = "111.111.111.16";

.port = "80";

.probe = www_probe; # 使用名为www_probe的健康检查策略

}

backend backend_17 {

.host = "111.111.111.17";

.port = "80";

.probe = www_probe; # 使用名为www_probe的健康检查策略

}

#默认后端

backend default {

.host = "111.111.111.40";

.port = "81";

}

###################################################################

# 配置后端集群事件

sub vcl_init {

# 后端集群有4种模式 random, round-robin, fallback, hash

# random         随机

# round-robin    轮询

# fallback        后备

# hash        固定后端 根据url(req.http.url) 或 用户cookie(req.http.cookie) 或 用户session(req.http.sticky)(这个还有其他要配合)

# 把backend_16 和 backend_17配置为轮询集群 取名为www_round_robin

new www_round_robin = directors.round_robin();

www_round_robin.add_backend(backend_16);

www_round_robin.add_backend(backend_17);

# 把backend_16 和 backend_17配置为随机选择集群 取名为www_random

new www_random = directors.random();

www_random.add_backend(backend_16,10);  # 设置backend_16后端的权重为10

www_random.add_backend(backend_17,5);   # 设置backend_17后端的权重为5

# 把backend_16 和 backend_17配置为固定后端集群 取名为www_hash 在recv调用时还需要添加东西 看recv例子

new www_hash = directors.hash();

www_hash.add_backend(backend_16,1);        # 设置backend_16后端的权重为1

www_hash.add_backend(backend_17,1);        # 设置backend_17后端的权重为1

}

#定义允许清理缓存的IP

acl purge {

# For now, I'll only allow purges coming from localhost

"127.0.0.1";

"localhost";

}

# 请求入口 这里一般用作路由处理 判断是否读取缓存 和 指定该请求使用哪个后端

sub vcl_recv {

##############################指定后端区域###########################

# 域名为 www.xxxxx.com 的请求 指定使用名为www_round_robin的后端集群  在集群名后加上 .backend() 如只使用单独后端 直接写后端名字即可 如 = backend_16;

if (req.http.host ~ "www.xxxxx.com") {

set req.backend_hint = www_round_robin.backend();

}

# 使用固定后端集群例子 使用名为www_hash的集群

if (req.http.host ~ "3g.xxxxx.com") {

set req.backend_hint = www_hash.backend(req.http.cookie);  # 根据用户的cookie来分配固定后端 可以指定其他分配规则

}

# 其他将使用default默认后端

#####################################################################

# 把真实客户端IP传递给后端服务器 后端服务器日志使用X-Forwarded-For来接收

if (req.restarts == 0) {

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") {

# 如果发起请求的客户端IP 不是在acl purge里面定义的 就拒绝

if (!client.ip ~ purge) {

return (synth(405, "This IP is not allowed to send PURGE requests."));

}

# 是的话就执行清理

return (purge);

}

# 如果不是正常请求 就直接穿透没商量

if (req.method != "GET" &&

req.method != "HEAD" &&

req.method != "PUT" &&

req.method != "POST" &&

req.method != "TRACE" &&

req.method != "OPTIONS" &&

req.method != "PATCH" &&

req.method != "DELETE") {

/* Non-RFC2616 or CONNECT which is weird. */

return (pipe);

}

# 如果不是GET和HEAD就跳到pass 再确定是缓存还是穿透

if (req.method != "GET" && req.method != "HEAD") {

return (pass);

}

# 缓存通过上面所有判断的请求 (只剩下GET和HEAD了)

return (hash);

}

# pass事件

sub vcl_pass {

# 有fetch,synth or restart 3种模式. fetch模式下 全部都不会缓存

return (fetch);

}

# hash事件(缓存事件)

sub vcl_hash {

# 根据以下特征来判断请求的唯一性 并根据此特征来缓存请求的内容 特征为&关系

# 1. 请求的url

# 2. 请求的servername 如没有 就记录请求的服务器IP地址

# 3. 请求的cookie

hash_data(req.url);

if (req.http.host) {

hash_data(req.http.host);

} else {

hash_data(server.ip);

}

# 返回lookup , lookup不是一个事件(就是 并非指跳去sub vcl_lookup) 他是一个操作 他会检查有没有缓存 如没有 就会创建缓存

return (lookup);

}

# 缓存命中事件 在lookup操作后自动调用 官网文档说 如没必要 一般不需要修改

sub vcl_hit {

# 可以在这里添加判断事件(if) 可以返回 deliver restart synth 3个事件

# deliver  表示把缓存内容直接返回给用户

# restart  重新启动请求 不建议使用 超过重试次数会报错

# synth    返回状态码 和原因 语法:return(synth(status code,reason))

# 这里没有判断 所有缓存命中直接返回给用户

return (deliver);

}

# 缓存不命中事件 在lookup操作后自动调用 官网文档说 如没必要 一般不需要修改

sub vcl_miss {

# 此事件中 会默认给http请求加一个 X-Varnish 的header头 提示: nginx可以根据此header来判断是否来自varnish的请求(就不用起2个端口了)

# 要取消此header头 只需要在这里添加 unset bereq.http.x-varnish; 即可

# 这里所有不命中的缓存都去后端拿 没有其他操作 fetch表示从后端服务器拿取请求内容

return (fetch);

}

# 返回给用户的前一个事件 通常用于添加或删除header头

sub vcl_deliver {

# 例子

# set resp.http.*    用来添加header头 如 set resp.http.xxxxx = "haha"; unset为删除

# set resp.status     用来设置返回状态 如 set resp.status = 404;

# obj.hits        会返回缓存命中次数 用于判断或赋值给header头

# req.restarts    会返回该请求经历restart事件次数 用户判断或赋值给header头

# 根据判断缓存时间来设置xxxxx-Cache header头

if (obj.hits > 0) {

set resp.http.xxxxx_Cache = "cached";

} else {

set resp.http.xxxxx_Cache = "uncached";

}

#取消显示php框架版本的header头

unset resp.http.X-Powered-By;

#取消显示nginx版本、Via(来自varnish)等header头 为了安全

unset resp.http.Server;

unset resp.http.X-Drupal-Cache;

unset resp.http.Via;

unset resp.http.Link;

unset resp.http.X-Varnish;

#显示请求经历restarts事件的次数

set resp.http.xxxxx_restarts_count = req.restarts;

#显示该资源缓存的时间 单位秒

set resp.http.xxxxx_Age = resp.http.Age;

#显示该资源命中的次数

set resp.http.xxxxx_hit_count = obj.hits;

#取消显示Age 为了不和CDN冲突

unset resp.http.Age;

#返回给用户

return (deliver);

}

#处理对后端返回结果的事件(设置缓存、移除cookie信息、设置header头等) 在fetch事件后自动调用

sub vcl_backend_response {

#后端返回如下错误状态码 则不缓存

if (beresp.status == 499 || beresp.status == 404 || beresp.status == 502) {

set beresp.uncacheable = true;

}

#如请求php或jsp 则不缓存

if (bereq.url ~ "\.(php|jsp)(\?|$)") {

set beresp.uncacheable = true;

#php和jsp以外的请求

}else{

#如请求html 则缓存5分钟

if (bereq.url ~ "\.html(\?|$)") {

set beresp.ttl = 300s;

unset beresp.http.Set-Cookie;

#其他缓存1小时 如css js等

}else{

set beresp.ttl = 1h;

unset beresp.http.Set-Cookie;

}

}

#开启grace模式 表示当后端全挂掉后 即使缓存资源已过期(超过缓存时间) 也会把该资源返回给用户 资源最大有效时间为6小时

set beresp.grace = 6h;

#返回给用户

return (deliver);

}

#返回给用户前的事件 可以在这里自定义输出给用户的内容

sub vcl_deliver {

}