Varnish介绍:
Varnish是一个反向HTTP代理,有时也被称为HTTP的加速器或网络加速器;它存在于真实服务器的前面(可能有多级代理),将来自于客户端的请求中的部分内容存储在自身的内存中,以减少服务器响应时间和网络带宽消耗。与Varnish类似的开源解决方案还有squid.
Varnish不仅仅是一个通过缓存数据加速服务的反向代理,根据其安装和配置,也可用来:
- web application firewall,
- DDoS attack defender,抵御DDos攻击
- hotlinking protector,链保护
- load balancer,
- integration point, 集成点
- single sign-on gateway,单点登录网关
- authentication and authorization policy mechanism,认证授权策略机制
- quick fix for unstable backends, 不稳定后台的快速修复
- HTTP router.
Manager Process:
Manager Process是主模块,包含了Varnish的一些二进制程序。管理器进程的任务是将任务(包括缓存)委托给子进程。管理程序确保每个任务总是有一个进程。
Manager Process的CLI(命令行接口)可通过两种方式进行管理:
①varnishadm:一个基于列表的管理命令程序,其与varnishd守护进程相连接。
②VAC-->vagent2:VAC(Varnish Administration Console)包括一个GUI和API,VAC是生产环境中最常用的实时图和统计数据工具,帮助确定Varnish缓存服务器的瓶颈和问题。VAC是一种varnish的缓存服务器组的管理控制台,也被称为高速缓存组。
缓存组是具有相同配置的varnish缓存服务器的集合。
Cacher Process:
- listen to client requests
- manage worker threads
- store caches
- log traffic
- update counters for statistics 更新统计计数器
Shared Memory Log:
varnish通过可以基于文件系统接口进行访问的共享内存区域来记录日志(shared memory log);默认是90MB;分为两部分:
前半部分是计数器;后半部分是客户端请求的数据;
要向使用Varnish,必须要配置好Varnish,而配置其前提是要先了解VCL(Varnish Configuration Language)。
VCL:是一种特殊的域语言用来描述Varnish缓存的请求处理和文件缓存策略的。
When a new configuration is loaded, the VCC process, created by the Manager process, translates the VCL code to C. This C code is compiled typically by gcc to a shared object. The shared object is then loaded into the cacher process.
当一个新的配置项被装载时,由管理进程创建出一个VCC进程,将VCL编译成C代码;之后C代码又被gcc编译器根据类型解释成一个共享对象,此对象接下来会被装入缓存进程中。
然而,VCL的工作流程被看作一个有限状态机
Varnish Finite State Machine
vcl_recv
vcl_hash:
vcl_hit
vcl_miss
vcl_purge
vcl_pipe
vcl_pass:
pass
hit_for_pass
vcl_backend_fetch
vcl_backend_response
vcl_backend_error
vcl_deliver
vcl_synth
vcl的语法: (1)//,#,/*...*/:注释 (2)sub $name:定义子例程 (3)不支持循环,但支持条件判断 (4)有内建变量 (5)使用终止语句return,没有返回值 (6)操作符:=,==,!=,~,&&,||
应用实例:
/*测试缓存命中与否*/ sub vcl_deliver{ if(obj.hits>0){ set resp.http.X-cache = "HIT via" + " " + server.ip; } else{ set resp.http.X-cache = "MISS via" + " " + server.ip; } } /*强制对某些资源的请求不检查缓存*/ sub vcl_resv{ if(req.url ~ "(?i)^/login" || req.url ~ "(?i)^/admin"){ return(pass); } } /*对特定类型的资源,如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;*/ sub vcl_backend_response{ if(beresp.http.cache-control !~ "s-maxage"){ if(beresp.url ~ "(?i)\.jpg$"){ set beresp.ttl = 7200s; unset beresp.http.Set-Cookie; } if(bereps.url ~ "(?i)\.css"){ set bereps.ttl = 3600; unset beresp.http.Set-Cookie; } } }
设置多个后端主机:
backend default{ .host = "172.18.100.67"; .port = "80"; } backend appsrv{ .host = "172.18.100.68"; .port = "80"; } sub vcl_recv{ if(req.url ~ "(?i)\.php$"){ set req.backend_hint = appsrv; } else{ set req.backend_hint = default; } }
缓存的负载均衡实现:
/*在default.vcl中写入:*/ import directors; backend websrv1{ .host = "192.168.1.101"; .port = "80"; } backend websrv2{ .host = "192.168.1.102"; .port = "80"; } sub vcl_init{ new websrvs = directors.round_robin(); websrvs.add_backend(websrv1); websrvs.add_backend(websrv2); } sub vcl_recv{ set req.backend_hint = websrvs.backend(); }
对后端主机做健康检测:
backend websrv1 { .host = "192.168.1.101"; .port = "80"; .probe = { .url = "/"; .interval = 1s; .window = 8; //表示最近检测的次数 .threshold = 5; //最近检测的次数中成功的次数 .timeout = 2s; //探测时的超时时长 } }