Varnish
缓存基本知识
程序的运行具有局部性特征
- 时间局部性 : 访问过的数据, 在很短的时间内能被再次访问
- 空间局部性 : 数据被访问到, 数据周边的其他数据也有可能被访问到
衡量缓存有效与否, 取决于缓存的命中率
缓存 : 解决传输速度不对等的问题, 将访问过的数据, 放置在更加高速的设备上进行访问.
热区数据 : 局部性的一个表现
- 时效性 : 缓存过期(原数据更新)—] 缓存清理
缓存命中率 : hit/(hit + miss) 0-100%
- 页面命中率 : 基于页面数量进行衡量
- 字节命中率 : 基于页面体积进行衡量
缓存与否 :
- 私有数据 : private, private cache
- 公共数据 : public, public or private cache
HTTP报文中与Cache相关的参数 :
响应报文内容 :
- no-store : 缓存内容不能保存到本地
- no-cache : 请求最新内容, 不请求缓存内容
- max-age : 缓存有效的最大时长
请求报文内容 :
- public : 允许所有内容被缓存
Varnish 组织架构
- Manager 进程
- Cacher 进程 : 包含多种类型的线程
-
- accept, worker, expiry…
- share memory log :
-
- 统计数据 : 计数器
-
- 日志区域 : 日志记录
- 配置接口 : VCL
-
- Varnish Configuration Language
vcl complier --] c complier --] shared object
- Varnish Configuration Language
- jamallog : 为了实现高效缓存的系统调用
Varnish 的程序环境 :
- /etc/varnish/varnish.params : 配置varnish 服务进程的工作特性, 监听地址和端口 缓存机制…
- /etc/varnish/default/.vcl : 配置各Child/Cache线程的工作属性:
- 主程序 : /usr/sbin/varnishd
- CLI Interface : /usr/bin/varnishadm
- Shared Memory Log 交互工具
-
- /usr/bin/varnishhist : 查看日志区域的历史数据
-
- /usr/bin/varnishlog : 对日志进行获取和管理
-
- /usr/bin/varnishncsa : 对NCSA 格式的日志进行获取和管理
-
- /usr/bin/varnishstat : 对程序统计的数据进行分析
-
- /usr/bin/varnishtop : 对数据进行排序
- 测试工具程序 : /usr/bin/varnishtest
- VCL 配置文件重载程序 : /usr/sbin/varnish_reload_vcl
- Systemd Unit File :
-
- /usr/lib/systemd/system/varnish.service : 主服务
-
- /usr/lib/systemd/system/varnishlog.service : 日志记录服务
-
- /usr/lib/systemd/system/varnishncsa.service : NCSA格式的日志服务
Varnish 的缓存存储机制 :
- malloc [size] : 定义可用空间的上限, 重启后所有缓存项失效
- file [path,[size,[granularity]]] : 文件存储, 黑盒, 重启后所有缓存项失效
- persistent ,path,size 试验阶段 .
Varnish 配置 :
选项 : 配置选项放置在/etc/varnish/varnish.params, 是Unit File 的EnvironmentFile
默认监听在6081端口上, 避免和当前所代理的服务冲突.
-a address[:port][,adress[:port]][...] 指明监听的地址和端口
-b host[:port] 指明后端的主机和端口
-C 测试, 输出C语言代码并且退出
-p param=value 设定参数的值[可指定多次]
-r param[,param ...] 设定指定参数为不可修改
-u user 指定运行的用户
-s [name=]type[,options] 定义缓存存储机制
-F : 运行于前台
-f config_file : 指定配置文件
-T [address[:port]] 指定管理地址和接口, 管理端的监听的地址和端口为127.0.0.1:6082
密钥文件安装后自动生成
重载VCL配置文件 : varnish_vcl_reload
使用varnishadm 配置varnish运行时参数
varnishadm -S /etc/varnish/secret -T :6082
help [[command]] : 获取帮助
ping [[timestamp]] : 查看缓存服务器的状态
auth [response] : 认证
quit : 退出CLI模式
banner : 显示
status : 显示Child进程的状态
start : 运行varnish
stop : 停止varnish
vcl.load [configname] [filename] : 载入新的VCL文件
vcl.inline [configname] [quoted_VCLstring] : 载入新的VCL文件并附加参数
vcl.use [configname] : 使用配置项(已加载的VCL)
vcl.discard [configname] : 删除VCL
vcl.list : 显示加载VCL的历史
param.show [-l] [[param]] : 显示所有的参数
param.set [param] [value] : 设置特定的参数
panic.show : 显示错误的子进程
panic.clear : 清除错误的子进程
storage.list : 列出存储设备
vcl.show [-v] [configname] : 显示具体VCL文件中的内容
backend.list [[backend_expression]] : 显示后端主机列表
backend.set_health [backend_expression] [state] : 设定后端主机的健康状态
ban [field] [operator] [arg] [&& [field] [oper] [arg]]... : 清理缓存
ban.list : 定义如何手动清理缓存
修改特定的配置项 :
varnish> param.set Param_Name Value
- 示例
param.set thread_pool_max 1000
VCL (varnish configuration language)
state engine : 状态引擎切换
- request : vcl_recv
- response : vcl_deliver
- vcl_hash -(hit)-> vcl_hit –> vcl_deliver
- vcl_hast -(miss)-> vcl_miss –> vcl_backend_fecth –> vcl_backend_response –> vcl_deliver
- vcl_hash -(purge)-> vcl_purge –> vcl_synth
- vcl_hash -(pipe)-> vcl_pipe
两个特殊引擎 :
- vcl_init : 在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
- vcl_fini : 所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;
vcl 的语法格式 :
- vcl version 说明vcl的版本
- //, #, /* */ 作为注释
- 子例程使用sub vcl_hit { } 进行声明
- 没有循环, 内建变量的使用首先于引擎
- 结束一个状态引擎使用一个keyword来结束, 使用return来决定如何结束状态引擎 return(vcl_miss)
- 一个状态引擎上的配置只对一个状态引擎起作用
VCL状态引擎
- 每一个请求都是被独立处理的
- 每一个请求与其他请求隔离
- 各个状态引擎相互隔离
- return(action) 指示退出一个状态进入下一个状态
- 内建VCL码, 一直生效并且附加在自定义的代码后面
三类主要语法
sub subroutine {
...
}
if CONDITION {
...
} else {
...
}
内建的函数和关键词
函数
- regsub(str, regex, sub) : 基于正则表达式进行查找, 查找到的第一个值进行替换
- regsuball(str, regex, sub) : 基于正则表达式进行查找, 查找到的所有值进行替换
- ban(boolean expression) : 基于判断条件对缓存空间进行缓存清理
- hash_data(input) : 对指定的数据进行hash计算
- synthetic(str) : 用于响应报文中的页面错误信息, 可用于客户端请求的重定向
关键字
- call subroutine : 调用一个子例程(sub XXXX)
- return(action) : 指明下一次的动作
- new :
- set : 设定一个变量的值
- unset : 取消一个变量的值
操作符
==, !=, ~, >, >=, <, <=
示例:
if (obj.hits>0){
set resp.http.X-Cache = "HIT via" + server.ip;
} else {
set resp.http.X-Cache = "MISS via" + server.ip;'
}
报文处理流程和对应处理函数的变量
处理函数 | 能使用的变量 |
---|---|
vcl_hash{ } | req.* |
vcl_pipe{ } | req.* |
bereq.* | |
vcl_hit{ } | req.* |
obj.* | |
vcl_miss{ } | req.* |
vcl_purge{ } | req.* |
vcl_pass{ } | req.* |
vcl_deliver { } | req.* |
resp.* | |
vcl.synth{ } | req.* |
resq.* |
常用变量:
bereq.*, req.*:
bereq.http.HEADERS
bereq.request:请求方法;
bereq.url:请求的url;
bereq.proto:请求的协议版本;
bereq.backend:指明要调用的后端主机;
req.http.Cookie:客户端的请求报文中Cookie首部的值;
req.http.User-Agent ~ "chrome"
beresp.*, resp.*:
beresp.http.HEADERS
beresp.status:响应的状态码;
reresp.proto:协议版本;
beresp.backend.name:BE主机的主机名;
beresp.ttl:BE主机响应的内容的余下的可缓存时长;
obj.*
obj.hits:此对象从缓存中命中的次数;
obj.ttl:对象的ttl值
server.*
server.ip
server.hostname
client.*
client.ip
- bereq.* varnish服务器向后端传递的请求
- server.* 与varnish服务器相关的变量
- client.* 与client端相关的变量
示例 : 强制对某类资源的请求不检查缓存
vcl_recv {
if(req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}
vcl_purge { } 用于清理单个URL对应的资源
vcl_ban { }清理给定表达式所匹配到的内容
定义后端主机的负载均衡
后端主机的负载均衡在于取得缓存时的负载均衡, 缓存服务器取得缓存后不再向后端主机请求内容
首先定义多个后端主机
backend server1 {
...
}
backend server2 {
...
}
之后在vcl中导入模块
sub vcl_init {
new GROUP_NAME = directors.round_robin();
GROUP_NAME.add_backend(server1);
GROUP_NAME.add_backend(server2);
}
# 在对接收到的报文分发到组GROUP_NAME 中所定义的主机
sub vcl_recv {
set req.backend_hint = GROUP_NAME.backend();
}
健康状态检测
backend BE_NAME {
.host =
.port =
.probe = {
.url=
.timeout=
.interval=
.window=
.threshhold=
}
}
.probe:定义健康状态检测方法;
.url:检测时请求的URL,默认为”/”;
.request:发出的具体请求;
.request =
“GET /.healthtest.html HTTP/1.1”
“Host: www.magedu.com”
“Connection: close”
.window:基于最近的多少次检查来判断其健康状态;
.threshhold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
.interval:检测频度; 后面要加上s的单位
.timeout:超时时长; 后面要加上s的单位
.expected_response:期望的响应码,默认为200;
检测方式单独配置的话, 将.probe 中的内容放到backend 外面, 单独定义成一个名称, 例如check.
probe check {
.url= /healthcheck.html;
.timeout= 1s;
.interval= 2s;
.window= 5;
.threshhold= 4;
}
# 引用
backend Server1 {
.host = 192.168.4.101;
.port = 80;
.probe = check;
}
这样就能启用对后端主机的健康状态检测了
线程相关的参数:
在线程池内部,其每一个请求由一个线程来处理; 其worker线程的最大数决定了varnish的并发响应能力;
- thread_pools:进程池,最好小于或等于CPU核心数量;
- thread_pool_max:每个线程池中的最大线程数量
- thread_pool_min:. 额外意义为“最大空闲线程数”;
- 最大并发连接数=thread_pools * thread_pool_max
- thread_pool_timeout:清理空闲进程
- thread_pool_add_delay:清理等待时间
- thread_pool_destroy_delay:销毁进程等待时间
主机名修改了之后会导致varnish服务启动错误, 需要手动修改/var/lib/varnish/目录下的目录为当前主机名/