Varnish 介绍和部署

一 、基础知识简介
1.1 CDN的全称是Content Delivery Network,即内容分发网络。
通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
使用CDN的好处:
1) 不用担心自己网站访客,在任何时间,任何地点,任何网络运营商,都能快速打开网站。
2)各种服务器虚拟主机带宽等采购成本,包括后期运维成本都会大大减少。
3)给网站直接带来的好处就是:流量,咨询量,客户量,成单量,都会得到大幅度提升。

1.2 Varnish
官方网站
https://varnish-cache.org/
http://book.varnish-software.com/4.0/
Varnish 由FreeBSD创始人之一Kamp开发,是一款高性能且开源的反向代理服务器和 HTTP 加速器,放在HTTP或NGINX服务器前端,缓存内容,反向代理是作为普通服务器向客户端显示的代理服务器。Varnish与传统的 squid 相比,具有性能更高、速度更快、管理更加方便等诸多优点。Varnish速度很快的主要原因是其缓存全部都是放在内存里的。
Varnish不仅仅是用缓存内容来加速你服务器的反向HTTP代理,根据安装情况,varnish也可以用作:
web应用防火墙,DDoS攻击防御者,热链保护器,负载平衡器,整合点,单点登录网关,认证授权策略机制,快速修复不稳定的后端和HTTP路由器。
1.2.1 varnish的特点
Varnish基于内存缓存,重启后数据将消失
利用虚拟内存方式,io性能好
支持设置0~60秒内的精确缓存时间
VCL配置管理比较灵活
32位机器上缓存文件大小为最大2G
具有强大的管理功能,例如top,stat,admin,list等
状态机设计巧妙,结构清晰
利用二叉堆管理缓存文件,达到积极删除目的

1.2.2 varnish的优缺点:
优点:Varnish采用了“Visual Page Cache”技术,所有缓存的数据都直接从内存读取。
Varnish稳定性比Squid高,宕机率很低。
通过Varnish管理端口,可以使用正则表达式快速、批量地清除部分缓存。
Varnish可以支持更多的并发连接。
缺点 :Varnish在高并发状态下,CPU、I/O和内存等资源的开销高于Squid。
Varnish的进程一旦挂起、崩溃或者重启,缓存的数据都会从内存中释放出来,此时的所有请求都会被发送到后端应用服务器上,在高并发的情况下,就会给后端服务器造成很大压力。

1.2.3 对象生命周期
对象:即HTTP响应消息的本地存储 .varnish的对象存储在内存中,并通过hash key进行寻址。
缓存对象具有原始时间戳t_origin和三个持续时间属性:1)TTL,2)grace和3)keep。
t_origin是在后端创建对象的时间。 一个对象生活在缓存中,直到经过之后TTL + grace + keep,该对象被Varnish守护进程删除。


1.3 VCL (Varnish Configuration Language)
varnish是一个专门用于描述varnish请求处理和文件缓存策略规则的语言。当一个新的配置加载后,Manager管理进程将会将其转换为C代码并编译,C代码被gcc编译成共享对象,然后共享对象被加载到cacher进程中。通过default.vcl来控制 varnish的缓存策略,通过子程序subroutine的返回值来控制varnish的动作。
VCL有多个状态引擎(state engine),状态之间存在相关性,每个状态引擎可使用return(x)指明关联至哪个下一级引擎,每个状态引擎对应于vcl文件中的一个配置段,即为subroutine。
子进程作用:添加自定义标头,更改Varnish错误消息的外观,在Varnish中添加HTTP重定向功能,清除内容以及定义缓存对象的哪些部分是唯一的。


1.3.1 VCL 函数
vcl_recv是Varnish第一个VCL子进程,将客户端请求解析为其基本数据结构之后执行。
vcl_recv主要用途:修改客户端数据以减少缓存的多样性,规范化客户端输入; 决定使用哪个Web服务器;根据客户端数据决定缓存策略;执行特定Web应用程序所需的重写规则;访问控制列表(ACL);安全屏障,例如针对SQL注入攻击;
vcl_recv 函数: 接收和处理请求,当请求到达并成功接收后被调用,判断请求的数据并决定如何处理请求;该函数返回值有这么些关键字:pass 表示进入pass模式,将请求交给vcl_pass 函数;pipe 表示进入pipe模式,将请求交个vcl_pipe函数;error code[reason] 表示返回’code’给客户端并放弃请求, 'code’是错误标示例如200 405等;'reason’是错误原因
vcl_pipe函数:该函数在进入pipe模式时被调用,用于将请求直接传递给后端主机,在请求和返回内容没有改变的情况下,将不变的内容返回给客户端,直到这个链接关闭。有返回值:error code[reason] ,pipe 。
vcl_pass函数: 该函数进入pass模式被调用,用于直接将请求发送给后端主机,后端主机响应后发送给客户端,不进行任何缓存,每次都返回最新内容,有返回值:error code[reason] ,pass
lookup函数: 表示在缓存中查找到被请求的对象,并且根据查找的结果交给vcl_hit函数(命中)或vcl_miss(未命中)函数处理.
vcl_hit函数:在执行lookup后,如果在缓存中找到对象,该函数将会被自动调用, 有返回值:deliver 表示找到内容发送给客户端,把控制权交给vcl_deliver函数;error code[reason] ;pass。
vcl_miss函数: 在执行lookup后,在缓存中没有找到对象,该函数被调用,该函数可用于判断是否从后端请求内容,有返回值:fetch 表示从后端获取内容,并把控制权交给vcl_fetch函数;error code[reason] 同vcl_recv ;pass。
vcl_fetch函数:从后端主机更新缓存获取内容后调用该函数,接着判断获取的内容是放入缓存还是直接给客户端,有返回值:error code[reason] ;pass ;deliver
  vcl_deliver函数:将在缓存中找到的内容发送给客户端调用的方法,有返回值:error code[reason] ;deliver。
  vcl_timeout函数:在缓存内容到期前调用该函数 ,有返回值: discard 表示中缓存中清除该内容 ;fetch 。
  vcl_discard函数:缓存内容到期后或者缓存空间不够时自动被调用, 有返回值:keep 表示在内容中保留该缓存;discard


1.3.2 VCL处理流程
Receive状态:请求处理的入口状态,根据VCL规则判断该请求应该在Pass或Pipe,还是进入Lookup(到本地缓存中查询)
Lookup状态:进入此状态后,会在hash表中查询数据,如果找到则进入Hit状态,否则进入Miss状态
Pass状态:在此状态下会进入后端获取内容,既进入Fetch状态
Fetch状态:从后端获取请求,发送请求,获得数据,并存储到本地
Deliver状态:将获取的数据发送给客户端,然后完成本次请求

1.3.3 VCL里面的变量,可以用在VCL函数中,用于逻辑处理
——请求到达后可以使用的内置公用变量:
req.backend    =>    指定对应的后端主机
server.ip      =>    表示服务器端IP
client.ip      =>    表示客户端IP
req.request    =>    指定请求的类型,如GET POST PUT DELETE
req.url      =>    知道请求的URL
req.proto      =>    表示客户端发起请求的HTTP协议版本
req.http.header  =>    表示请求中的头部信息
req.restarts    =>    表示请求重启的次数,默认最大值为4
—— VCL向后端主机请求时使用的内置变量
beresp.request   =>    指定请求的类型,如GET POST
beresp.url      =>    指定请求的地址
beresp.proto    =>    指定请求的协议版本号
beresp.http.header =>    对应请求的HTTP头信息
beresp.ttl      =>    表示缓存的周期,单位秒
——从cache或后端主机获取内容后可以使用的内置变量
obj.status     =>    表示返回的状态码,如200 404 500 等
obj.cacheable   =>    表示返回的内容是否可以缓存
obj.valid     =>    表示是否是有效的HTTP应答
obj.response   =>    表示应答的状态信息
obj.ttl      =>    表示返回内容的生存周期,单位秒
obj.lastuse    =>    表示上次请求到现在的间隔,单位秒
——客户端应答时可以使用的变量
resp.status    =>    表示返回给客户端的状态码
resp.proto    =>    表示返回给客户端的HTTP协议版本
resp.http.header =>    表示返回给客户端的头信息
resp.response   =>    表示返回给客户端的状态信息


1.3.5 VCL内置state engine 状态引擎
——Client Side
vcl_recv, vcl_pass, vcl_hit, vcl_miss, vcl_pipe, vcl_purge, vcl_synth, vcl_deliver
——vcl_recv
hash :vcl_hash ——在缓存中查找请求。
pass : vcl_pass ——它通过缓存查找,但pass不会将来自后端的响应存储在缓存中。vcl_pass可能会返回是三个动作:fetch、synth、或者是restart。
pipe : vcl_pipe ——创建一个全双工管道,将客户端请求转发到后端,且不查看其内容。后端回复被转发回客户端且不缓存其内容。pipe请求不会出现在任何日志中。
deliver : vcl_deliver——所有请求流程的公共最后退出点,除了通过vcl_pipe的请求。
(在vcl_deliver中常用的且被可被修改的变量是:
resp.http.*:发送个客户端的头部,它们可以被set和unset。
resp.status:状态码为200,404,503等
resp.reason:被返回给客户端的http状态信息
obj.hit:在对象上的cache-hits的数。因此,0代表miss,可以评估这个变量来轻松地显示响应是来自缓存命中还是未命中。
req.restarts:在VCL中发出的重启次数 - 如果没有发生,则返回0。)

synth : vcl_synth ——用于在Varnish中生成内容,错误消息可以在这里创建,或者重定向用户(301/302重定向);可以创建合成响应,在resp.http上设置合成响应的头部。
vcl_synth定义的对象绝不在缓存上存储,对立与vcl_backend_error定义的对象。


——vcl_hash:定义要用于缓存对象的hash key。
Hash key将一个缓存对象与另一个缓存对象区分开来,默认的VCL为vcl_hash添加主机名或ip地址,同时添加请求的url给cache hash。
lookup : 查找缓存状态,是一个操作。
hit :vcl_hit ——缓存查找命中后被调用,vcl_hit子进程通常通过调用含有deliver,restart或者synth的return()来进行终止。
miss : vcl_miss ——在请求对象没有被lookup操作找到时调用,包含有是否尝试从后端检索文档以及使用那个后端的策略。
pass,hit_for_pass :val_pass
purge : vcl_purge —— 在缓存中查找请求以便删除它。


——Backend Side 后端响应
vcl_backend_fetch ——vcl_backend_fetch 可以从vcl_miss或vcl_pass中调用。当vcl_backend_fetch从vcl_miss中调用时,抓取的对象会被缓存。如果vcl_backend_fetch被从vcl_pass中调用时,抓取的对象也不会被缓存的,即使是obj.ttl或obj.keep变量的值比0大。变量bereq.uncacheable,该变量指示出从后端来的对象请求是否被缓存。
vcl_backend_response
vcl_backend_error

两个特殊的引擎:
vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;


1.4Varnish软件包中的关键程序:
1.)varnishd 主程序
varnishd是主程序,启动后生成两个进程,Manager Process(父进程)和Cacher Process(子进程),前者在启动时读入配置文件并fork()出后者,同时具有CLI接口接收管理员的指令以用于管理后者,后者是真正处理缓存业务的进程,其下又可以生成若干线程,由这些若干线程完成缓存业务的处理并记录日志。
2)Varnishd 的启动选项 :# varnishd --help
-f : 指定配置文件位置
-a : varnish监听的本地地址和端口。
-P :PID文件位置,用来关闭Varnish
-s :cache配置。默认使用256M内存

3.)varnishadmin
varnishadm可以用来建立一个CLI来连接varnishd;
选项:
-n ident 通过这个名字连接varnishd;
-S secretfile 指定认证的密钥文件。这个需要和提供给varnishd的-S参数一致。只有它可以读取该文件的内容,并验证这个CLI连接;
-t timeout 操作的超时时间;
-T 连接指定地址和端口的管理接口


二、varnish的程序环境
/etc/varnish/default.vcl ## 缓存策略文件,也可以自己定义
/etc/varnish/varnish.params //定义启动时使用哪个vcl作为缓存策略
主程序: /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:varnish日志服务
/usr/lib/systemd/system/varnishncsa.service :varnish日志持久的服务


三 、部署varnish 服务器
#yum provides varnish
#yum -y install varnish
#rpm -qc varnish
#varnishd --help
#systemctl status varnishd


default.vcl: 例子
probe backend_healthcheck { #健康状况监测
.url = “/test1.html”; .timeout = 1s; .interval = 10s; .window = 5; .threshold = 2;}
backend web1 { #创建后端主机
.host = “192.168.50.138”; .port = “80”; .probe = backend_healthcheck;}
backend web2 {
.host = “192.168.50.139”; .port = “80”; .probe = backend_healthcheck;}
import directors;sub vcl_init { #创建后端主机组,基于round_robin轮转
new web_cluster = directors.round_robin(); web_cluster.add_backend(web1); web_cluster.add_backend(web2);}
acl purgers { #定义PURGE方法访问来源IP
“localhost”; “127.0.0.1”; “192.168.50.0”/24;}
sub vcl_recv {
if (req.url ~ “test.html”) { #测试页面不缓存 return(pass); }
if (req.method == “PURGE”)
{ #当发送PURGE请求的客户端不再acl中指定地址时,返回405状态代码,并提示Not allowed.
if (!client.ip ~ purgers) {
return(synth(405,“Not allowed”)); }
return(hash); }
if (req.http.X-Forward-For) { #为后端主机添加X-Forward-For首部
set req.http.X-Forward-For = req.http.X-Forward-For + “,” +client.ip; }
else { set req.http.X-Forward-For = client.ip; }
set req.backend_hint = web_cluster.backend(); return(hash);}

sub vcl_hit { #如果请求的是PURGE方法,命中的话返回200状态码。
if (req.method == “PURGE”) { return(synth(200,“Purged”)); }}

sub vcl_miss { if (req.method == “PURGE”) { return(synth(404,“Not in cache”)); }}

sub vcl_pass { if (req.method == “PURGE”) { return(synth(502,“PURGE on a passed object”)); }}

sub vcl_backend_response { if (bereq.url ~ “.(jpg|jpeg|gif|png)KaTeX parse error: Can't use function '\.' in math mode at position 80: … (bereq.url ~ "\̲.̲(html|css|js)”) { set beresp.ttl = 6000s; }
if (beresp.http.Set-Cookie) { return(deliver); }}

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; }}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值