Varnish 4.0 实战

阅读:321 2019-03-19 14:40:17 来源:开源中国

简介

varnish是一款高性能且开源的反向代理服务器和http加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的squid相比,varnish具有性能更高、速度更快、管理更加方便等诸多优点;

目前最新版本是4.0.0,而3.x的版本也是可以生产环境下使用的稳定版本,但yum源中的2.x版本过于陈旧,不建议使用;

varnish与squid的对比

相同点

都是一个反向代理服务器;

都是开源软件;

varnish的优势

varnish的稳定性很高,两者在完成相同负荷的工作时,squid服务器发生故障的几率要高于varnish,因为使用squid要经常重启;

varnish访问速度更快,因为采用了“visualpagecache”技术,所有缓存数据都直接从内存读取,而squid是从硬盘读取,因而varnish在访问速度方面会更快;

varnish可以支持更多的并发连接,因为varnish的tcp连接释放要比squid快,因而在高并发连接情况下可以支持更多tcp连接;

varnish可以通过管理端口,使用正则表达式批量的清除部分缓存,而squid是做不到的;

squid属于是单进程使用单核cpu,但varnish是通过fork形式打开多进程来做处理,所以可以合理的使用所有核来处理相应的请求;

varnish的劣势

varnish进程一旦hang、crash或者重启,缓存数据都会从内存中完全释放,此时所有请求都会发送到后端服务器,在高并发情况下,会给后端服务器造成很大压力;

在varnish使用中如果单个url的请求通过ha/f5等负载均衡,则每次请求落在不同的varnish服务器中,造成请求都会被穿透到后端;而且同样的请求在多台服务器上缓存,也会造成varnish的缓存的资源浪费,造成性能下降;

varnish劣势的解决方案

针对劣势一:在访问量很大的情况下推荐使用varnish的内存缓存方式启动,而且后面需要跟多台squid服务器。主要为了防止前面的varnish服务、服务器被重启的情况下,大量请求穿透varnish,这样squid可以就担当第二层cache,而且也弥补了varnish缓存在内存中重启都会释放的问题;

针对劣势二:可以在负载均衡上做url哈希,让单个url请求固定请求到一台varnish服务器上;

对比varnish3.x的主要改进

完全支持流对象;

可后台获取失效的对象,即client/backend分离;

新的vanishlog查询语言,允许对请求进行自动分组;

复杂的请求时间戳和字节计数;

安全方面的提升;

涉及vcl语法的改变点

vcl配置文件需明确指定版本:即在vcl文件的第一行写上vcl4.0;

vcl_fetch函数被vcl_backend_response代替,且req.*不再适用vcl_backend_response;

后端源服务器组director成为varnish模块,需importdirectors后再在vcl_init子例程中定义;

自定义的子例程(即一个sub)不能以vcl_开头,调用使用callsub_name;

error()函数被synth()替代;

return(lookup)被return(hash)替代;

使用beresp.uncacheable创建hit_for_pss对象;

变量req.backend.healty被std.healthy(req.backend)替代;

变量req.backend被req.backend_hint替代;

关键字remove被unset替代;

详见:https://www.varnish-cache.org/docs/4.0/whats-new/index.html#whats-new-index

架构及文件缓存的工作流程

varnish分为master进程和child进程;

master进程读入存储配置文件,调用合适的存储类型,然后创建/读入相应大小的缓存文件,接着master初始化管理该存储空间的结构体,然后fork并监控child进程;

child进程在主线程的初始化的过程中,将前面打开的存储文件整个mmap到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配;

对外管理接口分为3种,分别是命令行接口、telnet接口和web接口;

同时在运行过程中修改的配置,可以由vcl编译器编译成c语言,并组织成共享对象(sharedobject)交由child进程加载使用;

child进程分配若干线程进行工作,主要包括一些管理线程和很多worker线程,可分为:

accept线程:接受请求,将请求挂在overflow队列上;

work线程:有多个,负责从overflow队列上摘除请求,对请求进行处理,直到完成,然后处理下一个请求;

epoll线程:一个请求处理称为一个session,在session周期内,处理完请求后,会交给epoll处理,监听是否还有事件发生;

expire线程:对于缓存的object,根据过期时间,组织成二叉堆,该线程周期检查该堆的根,处理过期的文件,对过期的数据进行删除或重取操作;

http请求基本处理流程

varnish处理http请求的过程如下

receive状态(vcl_recv):也就是请求处理的入口状态,根据vcl规则判断该请求应该pass(vcl_pass)或是pipe(vcl_pipe),还是进入lookup(本地查询);

lookup状态:进入该状态后,会在hash表中查找数据,若找到,则进入hit(vcl_hit)状态,否则进入miss(vcl_miss)状态;

pass(vcl_pass)状态:在此状态下,会直接进入后端请求,即进入fetch(vcl_fetch)状态;

fetch(vcl_fetch)状态:在fetch状态下,对请求进行后端获取,发送请求,获得数据,并根据设置进行本地存储;

deliver(vcl_deliver)状态:将获取到的数据发给客户端,然后完成本次请求;

注:varnish4中在vcl_fetch部分略有出入,已独立为vcl_backend_fetch和vcl_backend_response2个函数;

内置函数(也叫子例程)

vcl_recv:用于接收和处理请求;当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求;

vcl_pipe:此函数在进入pipe模式时被调用,用于将请求直接传递至后端主机,并将后端响应原样返回客户端;

vcl_pass:此函数在进入pass模式时被调用,用于将请求直接传递至后端主机,但后端主机的响应并不缓存直接返回客户端;

vcl_hit:在执行lookup指令后,在缓存中找到请求的内容后将自动调用该函数;

vcl_miss:在执行lookup指令后,在缓存中没有找到请求的内容时自动调用该方法,此函数可用于判断是否需要从后端服务器获取内容;

vcl_hash:在vcl_recv调用后为请求创建一个hash值时,调用此函数;此hash值将作为varnish中搜索缓存对象的key;

vcl_purge:pruge操作执行后调用此函数,可用于构建一个响应;

vcl_deliver:将在缓存中找到请求的内容发送给客户端前调用此方法;

vcl_backend_fetch:向后端主机发送请求前,调用此函数,可修改发往后端的请求;

vcl_backend_response:获得后端主机的响应后,可调用此函数;

vcl_backend_error:当从后端主机获取源文件失败时,调用此函数;

vcl_init:vcl加载时调用此函数,经常用于初始化varnish模块(vmods)

vcl_fini:当所有请求都离开当前vcl,且当前vcl被弃用时,调用此函数,经常用于清理varnish模块;

vcl中内置公共变量

变量(也叫object)适用范围

注:某些地方略有出入,详细可参考官方文档;

变量类型详解

req:therequestobject,请求到达时可用的变量

bereq:thebackendrequestobject,向后端主机请求时可用的变量

beresp:thebackendresponseobject,从后端主机获取内容时可用的变量

resp:thehttpresponseobject,对客户端响应时可用的变量

obj:存储在内存中时对象属性相关的可用的变量

具体变量详见:https://www.varnish-cache.org/docs/4.0/reference/vcl.html#reference-vcl

优雅模式(garcemode)

varnish中的请求合并

当几个客户端请求同一个页面的时候,varnish只发送一个请求到后端服务器,然后让其他几个请求挂起并等待返回结果;获得结果后,其它请求再复制后端的结果发送给客户端;

但如果同时有数以千计的请求,那么这个等待队列将变得庞大,这将导致2类潜在问题:

惊群问题(thunderingherdproblem),即突然释放大量的线程去复制后端返回的结果,将导致负载急速上升;

没有用户喜欢等待;

故为了解决这类问题,可以配置varnish在缓存对象因超时失效后再保留一段时间,以给那些等待的请求返回过去的文件内容(stalecontent),配置案例如下:

上一篇: 网页搜集系统
相关文章
{{ v.title }}
{{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
你可能感兴趣
推荐阅读 更多>
推荐商标

{{ v.name }}

{{ v.cls }}类

立即购买 联系客服