Varnish基础与示例

Varnish基础与示例

Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合。
Varnish Configuration Language(VCL)是varnish配置缓存策略的工具,它是一种基于“域”(domain specific)
的简单编程语言,它支持有限的算术运算和逻辑运算操作、允许使用正则表达式进行字符串匹配、
允许用户使用set自定义变量、支持if判断语句,也有内置的函数和变量等.使用VCL编写的缓存策略通常保存至.vcl文件中,
其需要编译成二进制的格式后才能由varnish调用。
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
    /usr/bin/varnishstat
    /usr/bin/varnishtop     
测试工具程序:
    /usr/bin/varnishtest
VCL配置文件重载程序:
    /usr/sbin/varnish_reload_vcl
Systemd Unit File:
    /usr/lib/systemd/system/varnish.service   varnish服务
    /usr/lib/systemd/system/varnishlog.service  日志服务;
    /usr/lib/systemd/system/varnishncsa.service 日志持久的服务;

Varnish.params文件参数说明:

#自动重新装载缓存策略,1表示自动装载
RELOAD_VCL=1 
#默认的缓存策略文件路径
VARNISH_VCL_CONF=/etc/varnish/default.vcl
#监听的本机地址与端口
VARNISH_LISTEN_ADDRESS=172.16.253.190
VARNISH_LISTEN_PORT=80
#管理员登录时使用的主机与端口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
#管理员登录时使用的密钥文件
VARNISH_SECRET_FILE=/etc/varnish/secret
#缓存类型和大小 可使用malloc,file:使用file类型缓存文件属主属组应为varnish
VARNISH_STORAGE="file,/etc/varnish/cachedir,1G"
#运行时的用户与组
VARNISH_USER=varnish
VARNISH_GROUP=varnish
#运行时参数,可定义线程数等等,-p后可添加运行参数及其值
DAEMON_OPTS="-p thread_pools=3 -p thread_pool_min=50 -p thread_pool_max=2000"

Default.vcl文件暂不说明,示例时会有说明
varnish架构及文件缓存的工作流程
这里写图片描述
这里写图片描述
Varnish 处理 HTTP 请求的过程大致分为如下几个步骤。
1,Receive 状态(vcl_recv):也就是请求处理的入口状态,根据 VCL 规则判断该请求应该 pass(vcl_pass)
或是pipe(vcl_pipe),还是进入 lookup(本地查询)。
2,Lookup 状态:进入该状态后,会在 hash 表中查找数据,若找到,则进入 hit(vcl_hit)状态,否则进入 miss(vcl_miss)状态。
3,Pass(vcl_pass)状态:在此状态下,会直接进入后端请求,即进入 fetch(vcl_fetch)状态
4,Fetch(vcl_fetch)状态:在 fetch 状态下,对请求进行后端获取,发送请求,获得数据,并根据设置是否进行本地存储。
5,Deliver(vcl_deliver)状态:将获取到的数据发给客户端,然后完成本次请求。

VCL 内置公共变量
VCL 内置的公共变量可以用在不同的 VCL 函数中,下面根据使用的不同阶段进行介绍

当请求到达时,可以使用以下公共变量

req.backend 指定对应的后端主机
server.ip   表示服务器 IP
client.ip   表示客户端 IP
req.quest   请求的类型,例如 GET、HEAD 等
req.url 指定请求的地址
req.proto   表示客户端发起请求的 HTTP 协议版本
req.http.header 表示对应请求中的 HTTP 头部信息
req.restarts    表示重启次数,默认最大值为 4
req.http.Cookie:客户端的请求报文中Cookie首部的值
req.http.User-Agent:客户端浏览器类型
req.http.host : 客户端主机名称

Varnish 在向后端主机请求时,可以使用以下公共变量

bereq.http.HEADERS :表示对应请求中 HTTP 头部信息
bereq.request:请求方法;
bereq.url:请求的url;
bereq.proto:请求的协议版本;
bereq.backend:指明要调用的后端主机;

Varnish 在向后端主机请求返回响应时,可以使用以下公共变量

beresp.requset  指定请求类型,例如 GET、HEAD 等
beresp.url  表示请求地址
beresp.backend.name:BE主机的主机名;
beresp.status:响应的状态码;
beresp.proto:表示backend server HTTP 协议版本
beresp.http. HEADERS:从backend server 响应报文指定首部
beresp.ttl  表示缓存的生存周期,cache 保留时间(s)

从 cache 或是后端主机获取内容后,可以使用以下公共变量

obj.status  返回内容的请求状态码,例如 200302504 等
obj.cacheable   返回的内容是否可以缓存
obj.valid   是否有效的 HTTP 请求
obj.response    返回内容的请求状态信息
obj.proto   返回内容的 HTTP 版本
obj.hits:此对象从缓存中命中的次数
obj.ttl 返回内容的生存周期,也就是缓存时间,单位秒
obj.lastuse 返回上一次请求到现在的时间间隔,单位秒

对客户端应答时,可以使用以下公共变量

resp.status 返回给客户端的 HTTP 代码状态
resp.proto  返回给客户端的 HTTP 协议版本
resp.http.header    返回给客户端的 HTTP 头部消息
resp.response   返回给客户端的 HTTP 头部状态

请求/响应报文所在阶段对应的varnish变量
这里写图片描述
在default.vcl文件中进行示例操作:(后端服务器指向172.16.252.205:80)
示例1:强制对某类资源的请求不检查缓存:
为方便查看是否命中缓存,需在vcl_deliver中添加以下内容:
这里写图片描述
在vcl_recv中添加以下内容:
这里写图片描述
使用varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082进入varnish交互模式,操作如下
这里写图片描述
请求url包含admin字符串,则将请求传递给pass去后端提起响应内容,因为从未命中,obj.hits为0,返回miss from。
这里写图片描述
示例2:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的(s-maxage:其项在公共缓存中生命周期)
这里写图片描述
载入配置,使用配置,浏览器测试:
这里写图片描述
示例3:禁止curl进行访问(禁止某个类型浏览器访问)
这里写图片描述

这里写图片描述
示例4:修剪缓存对象purge
这里写图片描述
使用其他主机访问:
这里写图片描述
使用172.16.253.190主机进行访问(-X:指定请求类型):
这里写图片描述
修剪完成后,再次请求:
这里写图片描述
示例5:修剪缓存对象ban
这里写图片描述

这里写图片描述
使用其他主机测试:
这里写图片描述
示例6:使用多后端主机实现负载均衡

vcl 4.0;
import directors; 导入模块
probe check { 健康检查参数
    .url = "/"; 检查的路径
    .window = 8; 检查次数
    .threshold = 4; 最小健康次数
    .interval = 2s; 检查频率2秒一次
    .timeout = 1s; 超时时长
}
backend default { 定义后端主机
       .host = "172.16.252.205";
       .port = "80";
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
    .probe = check;
}
backend pic {
    .host = "172.16.253.145";
    .port = "80";
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
    .probe = check;
}
sub vcl_init {
    new grouphost = directors.round_robin();
    grouphost.add_backend(default);
    grouphost.add_backend(pic);
}
sub vcl_recv {
    set req.backend_hint = grouphost.backend();

示例7:根据cookie值选择后端主机

vcl 4.0;
import directors; 导入模块
probe check { 健康检查参数
    .url = "/"; 检查的路径
    .window = 8; 检查次数
    .threshold = 4; 最小健康次数
    .interval = 2s; 检查频率2秒一次
    .timeout = 1s; 超时时长
}
backend default { 定义后端主机
       .host = "172.16.252.205";
       .port = "80";
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
    .probe = check;
}
backend pic {
    .host = "172.16.253.145";
    .port = "80";
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
    .probe = check;
}
sub vcl_init {
    new grouphost = directors.hash();
    grouphost.add_backend(default,1);
    grouphost.add_backend(pic,1);
}
sub vcl_recv {
    set req.backend_hint = grouphost.backend(req.http.cookie);

下面是个简单的配置:

# configure
vcl 4.0;
import directors;
probe check {
    .url = "/";
    .window = 8;
    .threshold = 4;
    .interval = 2s;
    .timeout = 1s;
}
backend default {
    .host = "172.16.252.205";
    .port = "80";
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
    .probe = check;
}
backend pic {
    .host = "172.16.253.145";
    .port = "80";
    .connect_timeout = 0.5s;
    .first_byte_timeout = 20s;
    .between_bytes_timeout = 5s;
    .max_connections = 50;
    .probe = check;
}
sub vcl_init {
    new grouphost = directors.round_robin();
    grouphost.add_backend(default);
    grouphost.add_backend(pic);
}
acl purgers {
    "localhost";
    "127.0.0.1";
    "172.16.253.190";
}
sub vcl_recv {
    set req.backend_hint = grouphost.backend();
    if (req.url ~ "(?i)^/admin") {
        return(pass);
    }
    if (req.method == "PURGE"){
        if (client.ip !~ purgers) {
            return (synth(444,"Not enough authority to " + client.ip));
        }
        return(purge);
    }

    if (req.method == "BAN") {
        if (client.ip !~ purgers) {
            return (synth(444,"Not enough authority to " + client.ip));
        }
        ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
        return(synth(200,"Ban Added"));
    }
/*  if (req.http.User-Agent ~ "(?i)curl") {
        return (synth(405,"No good"));
    }
*/
    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;
        }
    }
}
sub vcl_backend_response {
    if (beresp.http.cache-control !~ "s-maxage") {
        if (bereq.url ~ "(?i)\.(jpg|jpeg|gif|png|css|js)$") {
            unset beresp.http.Set_Cookie;
            set beresp.ttl = 7200s;
        }
    }
}

sub vcl_deliver {
    if (obj.hits>0) {
        set resp.http.X-Cache = "HIT from " + server.ip;
    } else {
        set resp.http.X-Cache = "MISS from " + server.ip;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值