前文咱们聊了下http协议里的缓存控制机制以及varnish架构组件介绍,回顾请参考http://www.javashuo.com/article/p-qdsszhfu-kn.html;今天咱们来聊一下怎样配置使用varnish;html
前边咱们说到过varnish有两个配置文件,一个是/etc/varnish/varnish.params,这个配置文件主要是定义varnishd主控进程的一些运行时参数以及定义varnishd监听在那个套接字上,以及链接varnish使用的密钥文件;另一个配置文件是/etc/varnish/default.vcl这个配置文件实际上是varnish.params文件中指定的默认缓存策略配置文件,这个里面主要是配置缓存相关策略,用varnish专有配置语言vcl写的配置文件;咱们先来了解下varnish.params配置文件吧前端
[root@test_node1-centos7 ~]# vim /etc/varnish/varnish.params # Varnish environment configuration description. This was derived from # the old style sysconfig/defaults settings # Set this to 1 to make systemd reload try to switch VCL without restart. RELOAD_VCL=1 # Main configuration file. You probably want to change it. VARNISH_VCL_CONF=/etc/varnish/default.vcl # Default address and port to bind to. Blank address means all IPv4 # and IPv6 interfaces, otherwise specify a host name, an IPv4 dotted # quad, or an IPv6 address in brackets. # VARNISH_LISTEN_ADDRESS=192.168.1.5 VARNISH_LISTEN_PORT=6081 # Admin interface listen address and port VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 VARNISH_ADMIN_LISTEN_PORT=6082 # Shared secret file for admin interface VARNISH_SECRET_FILE=/etc/varnish/secret # Backend storage specification, see Storage Types in the varnishd(5) # man page for details. VARNISH_STORAGE="malloc,256M" # User and group for the varnishd worker processes VARNISH_USER=varnish VARNISH_GROUP=varnish # Other options, see the man page varnishd(1) #DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
提示:RELOAD_VCL这个参数主要是指定varnish是否支持不重启切换VCL配置文件,1表示支持,0表示不支持;这里通常都是设置成1,在工做中千万不要随意重启varnish,一旦重启好多缓存项都将失效,颇有可能由于缓存失效,前端访问压力压到后端真正的服务器上,致使服务器崩溃的状况;VARNISH_VCL_CONF该参数指定缓存策略配置文件,默认是default.vcl,咱们能够直接编辑这个文件,而后经过VCL编译编译成不一样的配置名称的vcl;VARNISH_LISTEN_PORT该参数指定varnishd对外提供访问的端口,一般状况在前面没有代理的状况,咱们须要把这个端口改为80或者443;VARNISH_ADMIN_LISTEN_ADDRESS该参数是指定varnish的管理接口接听地址,为了安全一般使用本机回环地址,防止远程链接;VARNISH_ADMIN_LISTEN_PORT该参数指定varnish的管理接口监听的端口,一般这个端口能够不用更改,由于管理接口通常都只有管理员使用;VARNISH_SECRET_FILE该参数指定varnish的管理接口链接所用到认证文件,一般不须要更改;VARNISH_STORAGE该参数指定varnish的缓存存储方式,varnish的缓存存储方式有三种,第一种是malloc内存存储,其配置语法是malloc[,size],这种存储方式重启后全部缓存项都将失效;第二种是file文件,配置语法file[,path[,size[,granularity]]],一般咱们只须要指定文件的路径及文件大小,这种磁盘文件存储的方式是黑盒,重启后全部缓存项都将失效;第三种也是磁盘文件的方式存储,和第二种不一样的是这种存储方式重启后全部缓存项都有效,可是这种存储方式在varnish4.0还处于试验阶段,因此咱们能用的就两种,一种是内存存储,一种是文件黑盒存储,这两种方式都是重启后全部缓存项失效,因此varnish缓存服务器上不能随意重启的;VARNISH_USER和VARNISH_GROUP这两个参数是指定varnishd进程的启动用户和组;DAEMON_OPTS是指定varnish运行时参数,每一个参数都须要用-p来加以指定,可重复屡次使用来指定不一样的参数;-r表示死定指定参数为只读状态;这里提示下varnish重载VCL配置文件是直接使用varnish的专用重载命令varnish_reload_vcl命令;了解了varnishd的vcl配置文件,接下来咱们修改下对外提供服务端端口,而后尝试启动varnish看看;node
提示:由于本机上运行的有httpd把80端口给占用了,我这里以8000端口为例对外提供服务;同时咱们也给定了varnish的缓存是基于文件黑盒存储方式,并指定其文件大小为500M;mysql
提示:能够看到varnish对外提供服务的端口已经起来了,可是用浏览器访问8000端口提示503,说后端server没有找到,这是由于默认状况下varnish指定的后端server是127.0.0.1:8080,咱们要配置后端主机server能够在defalult.vcl中配置;以下所示web
提示:以上配置表示默认后端提供web服务的主机地址是127.0.0.1,端口是8080;一般状况咱们是须要更改这个配置文件来指定后端主机和端口的,而后从新编译该配置文件而后加载使用;算法
提示::这样修改配置文件后,须要用varnishadm这个工具链接到varnish提供的命令行接口上去编译配置文件,而后再加载使用;首先咱们来讲说varnishadm这个工具怎么使用吧sql
[root@test_node1-centos7 ~]# varnishadm --help varnishadm: invalid option -- '-' usage: varnishadm [-n ident] [-t timeout] [-S secretfile] -T [address]:port command [...] -n is mutually exlusive with -S and -T [root@test_node1-centos7 ~]#
提示:以上是varnishadm命令的使用帮助,其实这个命令很好使用,咱们只须要用-S(大写)来指定secret文件,而后用-T来指定varnish主机管理接口监听的地址和端口便可,固然这样去链接就是交互式链接,会给咱们一个交互式界面输入命令操做varnish,若是不想交互式使用,在后面能够给命令,有点相似mysql这个工具的用法;接下来咱们用varinshadm这个工具来链接下varnish的管理接口;chrome
[root@test_node1-centos7 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 200 ----------------------------- Varnish Cache CLI 1.0 ----------------------------- Linux,3.10.0-693.el7.x86_64,x86_64,-sfile,-smalloc,-hcritbit varnish-4.0.5 revision 07eff4c29 Type 'help' for command list. Type 'quit' to close CLI session. quit 500 Closing CLI connection [root@test_node1-centos7 ~]#
提示:看到以上界面就表示用varinshadm工具成功链接到varinsh的管理接口上了,输入quit表示推出管理界面,输入help表示参看命令列表shell
[root@test_node1-centos7 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 200 ----------------------------- Varnish Cache CLI 1.0 ----------------------------- Linux,3.10.0-693.el7.x86_64,x86_64,-sfile,-smalloc,-hcritbit varnish-4.0.5 revision 07eff4c29 Type 'help' for command list. Type 'quit' to close CLI session. help 200 help [<command>] ping [<timestamp>] auth <response> quit banner status start stop vcl.load <configname> <filename> vcl.inline <configname> <quoted_VCLstring> vcl.use <configname> vcl.discard <configname> vcl.list param.show [-l] [<param>] param.set <param> <value> panic.show panic.clear storage.list vcl.show [-v] <configname> backend.list [<backend_expression>] backend.set_health <backend_expression> <state> ban <field> <operator> <arg> [&& <field> <oper> <arg>]... ban.list
提示:用varnishadm工具链接varnish后每执行一个命令就会返回相似http协议中的状态码的数字,其中200就表示命令成功执行并返回相应的内容,这个状态的意思有点相似http里的状态码意思;从上面的help列出命令列表来看,它列出了各个命令的基本使用方法,好比hep命令能够直接使用help表示类出命令列表及命令使用格式,help 某个命令表示查看某个命令的使用方法;以下,咱们要查看下ping命令的用法能够在命令行接口上敲help ping express
提示:从上面的帮助信息,咱们能够了解到ping命令的主要做用是看看varnish是否存活,咱们在varnish shell中敲ping命令返回200 和PONG 1585892735 1.0就表示varnish主机上存活的;
继续上面的话题,咱们修改了default.vcl配置文件,咱们须要怎么样去编译呢?接续查看命令帮助
提示:以上表示vcl.load命令的用法和说明,该命令主要是编译和加载VCL文件,使用方法是vcl.load +配置名称(这个名称是咱们自定义的,能够说任何合法名称)+配置文件名称;以下
提示:以上就表示编译default.vcl配置文件,并起名叫test1,咱们能够在varnish shell 中敲 vcl.list来查看当前有几个vcl配置
提示:能够看到有两个配置,一个是名字为boot的,其状态是active表示当前正在使用的,另外一个是咱们刚才编译指定的名称test1,状态是available表示有效的,能够用的,意思就是咱们可使用vcl.use来切换使用的;接下来咱们来看看vcl.use的用法,并尝试切换咱们新编译的配置;
提示:vcl.use命令主要用来切换至指定配置名称的配置;从上面的返回结果看,test1如今处于active的状态,表示如今varnish应用的是test1的配置;接下来咱们就能够在浏览器在尝试访问varnish对外提供访问的端口;
提示:能够看到咱们如今访问8000端口能够正常获得后端httpd服务器的响应;说明咱们配置的后端主机ip和端口没有问题;同时上面的结果来看,varnish也是一款反向代理服务软件,一般varnish能够作反向代理,可是它里面的调度算法很简单只有轮询和加权轮询,之因此算法少是由于它的强项不是作反向代理服务器来用,它的强项是作缓存服务器来用,响应客户端的请求,不多经过反向代理到后端取资源;
配置好varnish的后端web主机后,接下来咱们来了解下varnish的配置语言VCL的语法
VCL(varnish configuration lanuage)是“域”专有类型的配置语言,主要用于编写缓存策略的,VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此互相隔离;每一个状态引擎可以使用return(X)指明至那个下一级引擎;每一个状态引擎对应于vcl文件中的一个配置端,即为subroutine,大概处理流程是这样的,例如vcl_hash --> return(hit) -->vcl_hit;处理过程要看return是什么,return(hit)就表示下一级处理的subroutine是vcl_hit;
varnish4.0VCL语法有以下几点:
1)VCL文件必须是vcl 4.0;开始
示例:
提示:以上除了#号开头的表示现有配置生效的指令;“#”表示注释
2)//和#号和/**/都表示注释,前二者表示单行注释,最后一个表示多行注释;
3)subroutines必需要有sub关键字指定
示例:
提示:这就表示一个subroutine 名字为vcl_recv
4)没有循环,受限于引擎的内建变量
5)用return()函数的参数做为下一个操做的关键字来结束语句;用return来实现状态引擎切换;
VCL有限状态机特定:
1)每项请求分别处理;
2)每一个请求在任何给定时间都是独立于其余请求的;
3)状态是有相关性,但又各自隔离;
4)return(action);退出一种状态并指定varnish进入下一种状态;
5)内置的VCL代码始终存在,并附加在你本身的VCL下面;也就说咱们不写任何VCL代码,它默认都有本身内置的VCL代码,且这个代码始终不变;咱们能够用在varnish shell中使用vcl.show -v 指定配置名称来查看当前生效的配置详情(默认VCL代码+本身写的VCL配置代码),以下
[root@test_node1-centos7 ~]# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 200 ----------------------------- Varnish Cache CLI 1.0 ----------------------------- Linux,3.10.0-693.el7.x86_64,x86_64,-sfile,-smalloc,-hcritbit varnish-4.0.5 revision 07eff4c29 Type 'help' for command list. Type 'quit' to close CLI session. varnish> vcl.list 200 active 0 boot varnish> vcl.show -v boot 200 // VCL.SHOW 0 1221 input # # This is an example VCL file for Varnish. # # It does not do anything by default, delegating control to the # builtin VCL. The builtin VCL is called when there is no explicit # return statement. # # See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/ # and http://varnish-cache.org/trac/wiki/VCLExamples for more examples. # Marker to tell the VCL compiler that this VCL has been adapted to the # new 4.0 format. vcl 4.0; # Default backend definition. Set this to point to your content server. backend default { .host = "192.168.0.99"; .port = "80"; } sub vcl_recv { # Happens before we check if we have this in cache already. # # Typically you clean up the request here, removing cookies you don't need, # rewriting the request, etc. } sub vcl_backend_response { # Happens after we have read the response headers from the backend. # # Here you clean the response headers, removing silly Set-Cookie headers # and other mistakes your backend does. } 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. } // VCL.SHOW 1 5479 Builtin /*- * Copyright (c) 2006 Verdens Gang AS * Copyright (c) 2006-2014 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp <phk@phk.freebsd.dk> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * The built-in (previously called default) VCL code. * * NB! You do NOT need to copy & paste all of these functions into your * own vcl code, if you do not provide a definition of one of these * functions, the compiler will automatically fall back to the default * code from this file. * * This code will be prefixed with a backend declaration built from the * -b argument. */ vcl 4.0; ####################################################################### # Client side sub vcl_recv { if (req.method == "PRI") { /* We do not support SPDY or HTTP/2.0 */ return (synth(405)); } if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } if (req.method != "GET" && req.method != "HEAD") { /* We only deal with GET and HEAD by default */ return (pass); } if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } return (hash); } sub vcl_pipe { # By default Connection: close is set on all piped requests, to stop # connection reuse from sending future requests directly to the # (potentially) wrong backend. If you do want this to happen, you can undo # it here. # unset bereq.http.connection; return (pipe); } sub vcl_pass { return (fetch); } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (lookup); } sub vcl_purge { return (synth(200, "Purged")); } sub vcl_hit { if (obj.ttl >= 0s) { // A pure unadultered hit, deliver it return (deliver); } if (obj.ttl + obj.grace > 0s) { // Object is in grace, deliver it // Automatically triggers a background fetch return (deliver); } // fetch & deliver once we get the result return (fetch); } sub vcl_miss { return (fetch); } sub vcl_deliver { return (deliver); } /* * We can come here "invisibly" with the following errors: 413, 417 & 503 */ sub vcl_synth { set resp.http.Content-Type = "text/html; charset=utf-8"; set resp.http.Retry-After = "5"; synthetic( {"<!DOCTYPE html> <html> <head> <title>"} + resp.status + " " + resp.reason + {"</title> </head> <body> <h1>Error "} + resp.status + " " + resp.reason + {"</h1> <p>"} + resp.reason + {"</p> <h3>Guru Meditation:</h3> <p>XID: "} + req.xid + {"</p> <hr> <p>Varnish cache server</p> </body> </html> "} ); return (deliver); } ####################################################################### # Backend Fetch sub vcl_backend_fetch { return (fetch); } sub vcl_backend_response { if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Surrogate-control ~ "no-store" || (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "no-cache|no-store|private") || beresp.http.Vary == "*") { /* * Mark as "Hit-For-Pass" for the next 2 minutes */ set beresp.ttl = 120s; set beresp.uncacheable = true; } return (deliver); } sub vcl_backend_error { set beresp.http.Content-Type = "text/html; charset=utf-8"; set beresp.http.Retry-After = "5"; synthetic( {"<!DOCTYPE html> <html> <head> <title>"} + beresp.status + " " + beresp.reason + {"</title> </head> <body> <h1>Error "} + beresp.status + " " + beresp.reason + {"</h1> <p>"} + beresp.reason + {"</p> <h3>Guru Meditation:</h3> <p>XID: "} + bereq.xid + {"</p> <hr> <p>Varnish cache server</p> </body> </html> "} ); return (deliver); } ####################################################################### # Housekeeping sub vcl_init { return (ok); } sub vcl_fini { return (ok); } varnish>
提示:以上就是咱们没有写任何VCL配置代码,默认就有的VCL配置代码;从上面的配置来看,VCL配置语言主要有三类主要语法
第一类定义subroutine,主要格式是
sub subroutine { ... }
第二类是if else条件判断分支,格式以下
if CONDITION { ... } else { ... }
第三类就是每一个subroutine都是须要由return语句结尾,指定下一跳subroutine
了解了上面的基本语法,咱们再来看看VCL的内建函数和关键字
首先说函数吧,regsub(str,regex,sub)这个函数是VCL内置查找替换字串的一个函数,这个函数只会替换第一次匹配的字串,若是后面有多个字串匹配不予处理;regsuball(str,regex,sub)这个函数和上面的那个函数只有一个区别,这个函数是替换全部匹配的字串;ban(boolean expression)该函数用于清理缓存项的; hash_data(input)对input作hash计算;synthetic(str)该函数用户合成字符串,一般用于嵌入其余代码用;
关键字:call subroutine,return(action),new,set,unset
操做符:==, !=, ~, >, >=, <, <=,逻辑操做符&&,||,!,变量赋值=
内建变量大概有5类,分别是req.*表示由客户端发来的请求报文相关;如req.http.*就表示请求首部的变量,如req.http.User-Agent就表示引用http请求报文中的User-Agent首部的值;req.http.Referer就表示应用http请求首部Referer的值;bereq.*是有varnish发日后端主机的http请求相关;如bereq.http.*就表示引用发日后端主机的http请求首部的值,同req.http.*的逻辑上同样的;beresp.*:由BE主机响应给varnish的响应报文相关;resp.*:由varnish响应给client相关;这四类变量都是同一种逻辑,.http.*就表示引用http对应首部的值;obj.*是存储在缓存空间中的缓存对象的属性;
经常使用的变量:
bereq.*, req.*: bereq.http.HEADERS bereq.request:请求方法; bereq.url:请求的url; bereq.proto:请求的协议版本; bereq.backend:指明要调用的后端主机; req.http.Cookie:客户端的请求报文中Cookie首部的值; req.http.User-Agent ~ "chrome" beresp.*, resp.*: beresp.http.HEADERS beresp.status:响应的状态码; reresp.proto:协议版本; beresp.backend.name:BE主机的主机名; beresp.ttl:BE主机响应的内容的余下的可缓存时长; obj.* obj.hits:此对象从缓存中命中的次数; obj.ttl:对象的ttl值 server.* server.ip server.hostname client.* client.ip
用户指定变量用set指令来设置,unset表示删除之意;
示例:指定响应首部,若是命中缓存就把对应首部的值设置成“HIT via ”+服务端ip地址,没有命中对应首部的值就是“MISS via” +服务端ip地址
提示:以上这段配置须要写在vcl_deliver中,vcl_deliver主要是varnish响应客户端报文都要经由它处理;有点相似iptables里的postrouting;
测试,在浏览器中访问,看看响应首部X-Cache的值就能够判断该此请求是否被缓存命中;
第一次访问,确定是不会被缓存命中,由于压根就没有缓存,谈不上命中,因此第一次访问X-Cache首部的值应该是"MISS via 192.168.0.99"
提示:能够看到第一次访问的确是MISS的,那么第二次和后面的访问会不会是miss的呢?
提示:第二次访问X-Cache响应首部的值就变成了hit via 192.168.0.99 说明第二次访问被缓存命中了;