缓存varnish的管理及配置详解

一 工作原理

在当前主流的Web服务架构体系中,Cache担任着越来越重要的作用。常见的基于浏览器的C/S架构,Web Cache更是节约服务器资源的关键。而最近几年由FreeBSD创始人之一Kamp开发的varnish更是一个不可多得的Web Cache Server。严格意义上说,Varnish是一个高性能的反向代理软件,只不过与其出色的缓存功能相比,企业更愿意使用其搭建缓存服务器。同时,由于其工作在Web Server的前端,有一部分企业已经在生产环境中使用其作为旧版本的squid的替代方案,以在相同的服务器成本下提供更好的缓存效果,Varnish更是作为CDN缓存服务器的可选服务之一。

Varnish主要有以下几点特性:
 1.缓存位置:可以使用内存也可以使用磁盘。如果要使用磁盘的话推荐SSD做RAID1
 2.日志存储:日志也存储在内存中。存储策略:固定大小,循环使用
 3.支持虚拟内存的使用。
 4.有精确的时间管理机制,即缓存的时间属性控制。
 5.状态引擎架构:在不同的引擎上完成对不同的缓存和代理数据进行处理。可以通过特定的配置语言设计不同的控制语句,以决定数据在不同位置以不同方式缓存。类似于netfilter中的钩子,在特定的地方对经过的报文进行特定规则的处理。
 6.缓存管理:以二叉堆格式管理缓存数据,做到数据的及时清理。


二 基本架构

1. 状态引擎

2.内部处理流程

三 配置详解

1. 简单安装

[root@node1 ~]# yum install varnish -y

 

2. 配置详解

[root@node1 ~]# cd /etc/varnish


配置default.vcl配置文件

[root@node1 varnish]# cat default.vcl
# 使用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.xiaxiaodie.com"        # 访问的域名为www.xiaxiaodie.com
 "Connection: close";        # 检查完关闭连接
#其他参数 如 超时时间 检查间隔 等 均使用默认
}
##################################################################
#######################配置后端区域################################
backend backend_15 {
 .host = "172.18.67.15";
 .port = "80";
 .probe = www_probe; # 使用名为www_probe的健康检查策略
}
backend backend_16 {
 .host = "172.18.67.16" 
 .port = "80";
 .probe = www_probe; # 使用名为www_probe的健康检查策略
}
#默认后端
backend default {
 .host = "172.18.67.15" 
 .port = "80";
}
###################################################################
# 配置后端集群事件
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_15 和 backend_16配置为轮询集群 取名为www_round_robin
 new www_round_robin = directors.round_robin();
 www_round_robin.add_backend(backend_15);
 www_round_robin.add_backend(backend_16);
 # 把backend_15 和 backend_16配置为随机选择集群 取名为www_random
 new www_random = directors.random();
 www_random.add_backend(backend_15,10);  # 设置backend_15后端的权重为10
 www_random.add_backend(backend_16,5);   # 设置backend_16后端的权重为5
 # 把backend_15 和 backend_16配置为固定后端集群 取名为www_hash 在recv调用时还需要添加东西 看recv例子
 new www_hash = directors.hash();
 www_hash.add_backend(backend_15,1);        # 设置backend_15后端的权重为1
 www_hash.add_backend(backend_16,1);        # 设置backend_16后端的权重为1
}
#定义允许清理缓存的IP
acl purge {
# For now, I'll only allow purges coming from localhost
 "127.0.0.1";
 "localhost";
}
# 请求入口 这里一般用作路由处理 判断是否读取缓存 和 指定该请求使用哪个后端
sub vcl_recv {
 # 域名为 www.xiaxiaodie.com 的请求 指定使用名为www_round_robin的后端集群  在集群名后加上 .backend() 如只使用单独后端 直接写后端名字即可 如 = backend_16;
 if (req.http.host ~ "node2") {
  set req.backend_hint = www_round_robin.backend();
 }
 # 使用固定后端集群例子 使用名为www_hash的集群
 if (req.http.host ~ "3g.xiaxiaodie.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.xiaxiaodie = "haha"; unset为删除
 # set resp.status     用来设置返回状态 如 set resp.status = 404;
 # obj.hits        会返回缓存命中次数 用于判断或赋值给header头
 # req.restarts    会返回该请求经历restart事件次数 用户判断或赋值给header头
 # 根据判断缓存时间来设置xiaxiaodie-Cache header头
 if (obj.hits > 0) {
  set resp.http.xiaxiaodie_Cache = "cached";
 } else {
 set resp.http.xiaxiaodie_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.xiaxiaodie_restarts_count = req.restarts;
 #显示该资源缓存的时间 单位秒
 set resp.http.xiaxiaodie_Age = resp.http.Age;
 #显示该资源命中的次数
 set resp.http.xiaxiaodie_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);
}

 

配置varnish.params配置文件

[root@node1 varnish]# vim varnish.params
# Varnish environment configuration description. This was derived from
# the old style sysconfig/defaults settings
# Set this to 1 to make systemd reload try to switch VCL without restart.
RELOAD_VCL=1
# Main configuration file. You probably want to change it.
VARNISH_VCL_CONF=/etc/varnish/default.vcl
# Default address and port to bind to. Blank address means all IPv4
# and IPv6 interfaces, otherwise specify a host name, an IPv4 dotted
# quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=192.168.1.5
VARNISH_LISTEN_PORT=80
# Admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
# Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret
# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details.
VARNISH_STORAGE="malloc,256M"
# User and group for the varnishd worker processes
VARNISH_USER=varnish
VARNISH_GROUP=varnish
# Other options, see the man page varnishd(1)
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"

 

3.简单管理工具

[root@node1 varnish]# varnishadm -S secret -T 127.0.0.1:6082
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-327.el7.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-4.0.4 revision 386f712
Type 'help' for command list.
Type 'quit' to close CLI session.
help
200        
help [<command>]
ping [<timestamp>]
auth <response>
quit
banner
status
start
stop
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
param.show [-l] [<param>]
param.set <param> <value>
panic.show
panic.clear
storage.list
vcl.show [-v] <configname>
backend.list [<backend_expression>]
backend.set_health <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
ban.list

 

四 访问测试

[root@node1 varnish]# systemctl start varnish.service

posted @ 2017-05-21 17:40  SimonLiu91  阅读(1738)  评论(0编辑  收藏  举报