Varnish
管理进程:编译VCL并应用新配置,监控varnish,初始化varnish, CLI接口
Child/cache:
- Acceptor: 接收新的连接请求
- worker threads: 处理用户请求
- Expiry: 清理缓存中的过期对象
日志:Shared Memory Log,共享内存日志大小默认一般为90MB,分为两步分,前一部分为计数器,后一部分为请求相关的数据。
VCL:Varnish Configuration Language 域风格简单配置语言,缓存策略配置接口
varnish如何存储缓存对象:
- file:单个文件,不支持持久机制,重启之后缓存全部失效
- malloc:内存,把所有缓存对象缓存在内存中
- persistent:基于文件的持久存储
配置varnish的三种应用:
-
varnishd应用程序的命令行参数:监听的socket,使用的存储类型等等,额外的配置参数: -p param=value -r param,param设定只读参数列表
/etc/varnish/varnish.params
-
-p选项指明的参数:
运行时参数:可在程序运行中,通过CLI进行配置
-
vcl:配置缓存系统的缓存机制:
通过vcl配置文件进行配置,先编译,后应用,依赖于c编译器
/etc/varnish/default.vcl
命令行工具:
varnishadm -S /etc/varnish/secret -T IP:PORT
Log:
varnishlog
varnishncsa
Statistics
varnishstat
Top:
varnishtop
vcl:
- state engine:各引擎之间存在一定的相关性:前一个engine如果有多个下游engine,则上游engine需要用return指明要转移的下游engine
- vcl_recv
- vcl_hash
- vcl_hit
- vcl_miss
- vcl_fetch
- vcl_diliver
- vcl_pipe
- vcl_pass
- vcl_error
vcl编程语法:
//,#, /* */用于注释,会被编译器忽略
sub $name: 用于定义子例程
不支持循环
有众多内置的变量,变量的可调用位置与state engine有密切的相关性
支持终止语句,return(action):没有返回值
域专用
操作符= , == , &&,~,||, !
条件判断语句:
if (condtion) {
} else {
}
变量赋值:set name=value
unset name
req.http.HEADER: 调用request报文中http协议的指定的HEADER首部
req.http.X-Forwarded-For
req.http.Authorization
req.http.cookie
req.request: 请求方法
client.ip : 客户端IP
state engine 流程(v3);
- vcl_rec –> vcl_hash –>vcl_hit –> vcl_deliver 缓存命中 varnish直接投递
- vcl_recv –> vcl_hash–> vcl_miss –> vcl_fetch –> vcl_deliver 缓存没有命中,从后端服务器去取
- vcl_recv –> vcl_pass –> vcl_fetch –> vcl_deliver 强制到后端服务器取数据
- vcl_recv –> vcl_pipe 理解不了客户端的请求 ,直接发送给后端服务器,实现管道
state engine (v4)
- vcl_recv
- vcl_pass
- vcl_pipe
- vcl_pipe
- vcl_hit
- vcl_miss
- vcl_backend_fetch
- vcl_backend_response
- vcl_backerd_error
- vcl_purge
- vcl_systh
定义在vcl_deliver中,向响应给客户端的报文添加一个自定的首部X-Cache来显示是否命中缓存
sub vcl_deliver {
# Happens when we have all the pieces we need, and are about to send the
# response to the client.
#
# You can do accounting or modifying the final object here.
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
}else {
set resp.http.X-Cache = "Miss";
varnish的内置变量
-
req 客户端发送的请求
-
resp 响应客户端相关变量
-
bereq开头变量 向后端服务器取资源
-
beresp 开头变量 ,收到的后端服务器的响应报文
-
server开头变量 varnish本身
-
obj开头变量 从后端服务器收到响应以后其中内容的属性
-
storage
breq:
- bereq.http.HEADERS: 由varnish发往backend server 的请求报文的指定首部
- bereq.requests :请求方法
- bereq.url
- bereq.proto: 使用的协议版本 http/1.1 1.0
beresp:
- beresp.proto 后端服务器响应式的协议版本
- beresp.http.HEADER: 从backend server 响应的报文的首部
- beresp.backend.ip 后端服务器的IP
- beresp.backend.name 后端服务器的主机名称
- beresp.reason 后端服务器的响应原因短语
- beresp.status 后端服务器的响应状态码
- beresp.ttl 后端服务器响应对象剩余的生存时长
- bereq.backend: 指明要调用的后端主机
obj:
-
obj.hits: 缓存对象命中次数
-
obj.ttl: 对象的TTL值
req:
-
req.method: 请求的方法
resp:
-
resp.status
server:
-
server.ip varnish服务器IP
-
server.hostname 服务器的主机名
storage:
-
storage.
.free_space: 剩余空间 -
storage.
.used_space 已用空间 详细参考官方文档
设置支持虚拟主机:
if (req.http.host == “www.linux.com”) {
}
强制对某资源的请求,不检查缓存:
if (req.url ~ “^test7.html$”) {
return(pass);
}
不允许缓存,/admin 和 /login的请求
if (req.url ~ "(?i)^/login" || req.rul ~ "(?i)^/admin") {
return(pass);
}
对特定类型的资源取消其私有的cookie标识(放在vcl_backend_response中),并强行设定其可以varnish缓存的时长:
if (beresp.http.cache-control !~ "s-maxage") {
if (bereq.url ~ "(?i).jpg$") {
set beresp.ttl = 3600s;
unset beresp.http.Set-Cookie;
}
if (bereq.url ~ "(?i).css$") {
set beresp.ttl = 600s;
unset beresp.http.Set-Cookie;
}
}
backend server的定义:
-
backend name {
.attribute = “value”;
}
.host: BE主机的IP
.port BE主机监听的端口
.probe: 对BE做健康状态检测
.max_connections: 并发连接最大数量
后端主机的健康检测方式:
probe name {
.attribute = “value”;
}
.url : 判定BE健康有要请求的URL
.expected_response : 期望的响应状态码 默认为200
动静分离示例配置
vcl 4.0;
backend websrv1 {
.host = "192.168.175.5";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
backend websrv2 {
.host = "192.168.175.4";
.port = "80";
.probe = { #设置健康检查的文件
.url = "/test1.html";
}
}
sub vcl_recv {
if (req.url ~ "(?i)^/login" || req.url ~ "(?i)^/admin") { #如果以admin或login开头就不缓存
return(pass);
}
if (req.url ~ "(?i).(jpg|png|gif)$") { #动静分离配置
set req.backend_hint = websrv1;
}else {
set req.backend_hint = websrv2;
}
}
sub vcl_backend_response {
}
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
}else{
set resp.http.X-Cache = "Miss";
}
}
示例2:负载均衡配置
vcl 4.0;
backend websrv1 {
.host = "192.168.175.5";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
backend websrv2 {
.host = "192.168.175.4";
vcl 4.0;
backend websrv1 {
.host = "192.168.175.5";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
backend websrv2 {
.host = "192.168.175.4";
.port = "80";
.probe = {
.url = "/test1.html";
}
}
import directors;
sub vcl_init {
new mycluster = directors.round_robin();
mycluster.add_backend(websrv1);
mycluster.add_backend(websrv2);
}
sub vcl_recv {
set req.backend_hint = mycluster.backend();
}
sub vcl_backend_response {
}
sub vcl_deliver {
if (obj.hits>0) {
set resp.http.X-Cache = "HIT";
}else{
set resp.http.X-Cache = "Miss";
}
}
#注意此处是对资源的负载均衡而不是对单个文件的负载均衡,访问一个文件到1服务器,访问另一个负载到2服务器(有点坑爹)
负载均衡算法:
- fallback
- random
- round_robin
- hash
掌握:varnishlog, varnishncsa, varnishtop, varnishstat