Linux运维 第三阶段 (十八) varnish

  1. 云栖社区>
  2. 博客>
  3. 正文

Linux运维 第三阶段 (十八) varnish

技术小阿哥 2017-11-28 14:57:00 浏览1214
展开阅读全文

数据:

结构化数据,RDBMS

非结构化数据,FS,存海量小文件,NASSANDFS可提供较好的性能;

 

web cache

程序具有局部性(时间局部性;空间局部性);

key-valuekeyurl访问路径,hash),valueweb content);

hotpot热点数据;

命中率=hit/(hit+miss),文档命中率(从文档个数进行衡量),字节命中率(从内容大小进行衡量);

缓存对象,有生命周期,定期清理;

缓存空间耗尽,LRU算法;

可缓存,不可缓存(用户私有数据);

cache is king

 

缓存的处理步骤:

接收请求-->解析请求(提取请求的URL及各种首部)-->查询缓存-->新鲜度检测-->创建响应报文-->发送响应-->记录日志;

 

新鲜度检测机制:

过期日期:

http/1.0Expires,时区不同则有问题;

http/1.1Cache-Control: max-age=600,该网页内容最多存活时间,比Expires要好;

有效性再验证,revalidate

如果原始内容未改变,则仅响应首部(不附带body部分),响应码304Not Modified);

如果原始内容发生改变,则正常响应,响应码200

如果原始内容消失,则响应404,此时缓存中的cache object也应被删除;

 

条件式请求首部:

If-Modified-Since(基于请求内容的时间戳作验证);

If-Unmodified-Since

If-Match

If-None-MatchEtag);

 

Cache-Controlcache-directive   #(更加灵活的缓存控制机制)

cache-request-directive请求:

no-cache(不要缓存的实体,要求现在从web server上取);

max-age(只接受Age值小于max-age值,并且没有过期的对象);

max-stale(可以接受过去的对象,但过期时间必须小于max-stale值);

min-fresh(接受其新鲜生命期大于其当前Agemin-fresh值之和的缓存对象);

no-store;

no-transform;

only-if-cached;

cache-extension;

cache-response-directive响应:

public(可以用cached内容回应任何用户);

private(只能用缓存内容回应先前请求该内容的那个用户);

no-cache(可以缓存,但只有在跟web server验证其有效后,才能返回给client);

max-age(本响应包含的对象的过期时间);

ALL:no-store(不允许缓存);

no-transform;

must-revalidate;

proxy-revalidate;

s-maxage;

cache-extenion;

 

 

HTTP Expiration

缓存过期,则一定会到原始server上去取,但原始server上的内容未必发生改变;

wKioL1lfPTLQDzkcAACID4e-yrc068.jpg

wKioL1lfPUSD2dpIAAB7IpNppd8460.jpg

wKiom1lfPVbDwbWgAACOp-7dsSs651.jpg

 

HTTP validation

Last-Modified/If-Modified-Since

Etag/If-None-Match

wKioL1lfPWeQ0WOXAACJ6Azn7eM458.jpg

wKioL1lfPXTjcO8RAACYelCArr4800.jpg

wKioL1lfPYuwzRoWAACYY0yXCS8992.jpg

 

两者结合:

you can combie HTTP headers the way you want,Expiration wins over Validation

wKiom1lfPZ6hViheAACQB04SUZg424.jpg

wKioL1lfParTkHs5AACAw7wIqcs941.jpg

wKioL1lfPbeD3pHtAACaVhUEIAY994.jpg

wKioL1lfPcWQi5QvAACrrpv25PA869.jpg

wKioL1lfPsezeCdqAACepIZgpfM438.jpg

wKioL1lfPtiCOgS7AACpN34BDeA173.jpg

 

常见的缓存服务器开源解决方案:

varnish VS squid(类似nginx VS httpd);

 

CDNGSLB,缓存路由协议;大公司,全国各机房自建CDN;中小公司租用 第三方CDN,帝联、蓝讯等);

 

http://www.varnish-cache.org/

 

varnish architecture

wKiom1lfPvDzyqqEAADSwJXGC3E692.jpg

 

DSLdomain specific language

VCLvarnish configuration language,缓存策略配置接口,基于域的简单编程语言;

管理进程(编译vcl并应用新配置,监控varnish,初始化varnishCLI接口);

child/cacheacceptor(接收新的连接请求);worker threads(处理用户请求);Expiry(清理缓存中的过期对象));

单进程多线程;

日志(shared memory log,默认90M,分为两部分,前一部分是计数器,后一部分是请求相关的数据);

 

内存分配和回收:

malloc()free()   #(这两种效率不高);

jemalloc   #General-purpose scalable concurrent malloc(3) implementation,更高效)

 

varnish如何存储缓存对象:

方式一:file(单个文件;不支持持久机制;适用于大量文件,最好用pci-e disk;与nginx缓存不同,varnish将所有缓存对象存放在单个文件中,varnish自己管理这个文件,varnish在这个文件内部组织出专用的FSvarnish自己识别每一个缓存对象从哪开始到哪结束,名字等元数据,varnish用于缓存的这一单个文件是独立自治的王国;varnish服务在运行过程中不能随便重启,否则缓存全部失效);

注:

nginx将缓存对象放在disk中,key在内存里,nginx缓存在定义时有多级缓存目录,levels=1:2:2,目录下放缓存对象,每一个缓存对象用一个文件来存,因此会有很多文件描述符inode

方式二:malloc(在内存中存放缓存对象,时间久了有内存碎片);

方式三:persistent(基于文件的持久存储,实验阶段,有io问题,最好用SSD disk);

 

配置varnish的三种接口:

1varnishd应用程序的命令行参数:

监听的socket,使用的存储类型等额外的配置参数;

-p param=value

-r param,param,……   #(设定只读参数列表)

2-p选项指明的参数,run-time运行时参数,可在程序运行时,通过其CLI进行配置;

3vcl,配置缓存系统的缓存机制,通过vcl配置文件进行配置,先编译(依赖c compilegcc),后应用,/etc/varnish/default.vcl

 

 

 

]#yum -y install varnish   #2 version-->3的配置不兼容,3-->4兼容)

Package(s)data still to download: 455 k

(1/3):jemalloc-3.6.0-1.el6.x86_64.rpm                                                  | 100 kB     00:00    

(2/3):varnish-2.1.5-6.el6.x86_64.rpm                                                   | 264 kB     00:00    

(3/3):varnish-libs-2.1.5-6.el6.x86_64.rpm                                              |  90 kB     00:00   

 

]#varnishd -V

varnishd(varnish-2.1.5 SVN )

Copyright(c) 2006-2009 Linpro AS / Verdens Gang AS

 

]#varnishd -h   #(默认listen 6081/60826081服务端口,6082admin端口,haproxy默认5000

    -a address:port              # HTTP listen address and port

    -b address:port              # backend address and port

                                 #    -b <hostname_or_IP>

                                 #   -b '<hostname_or_IP>:<port_or_service>'

    -f file                      # VCL script

    -s kind[,storageoptions]     # Backend storage specification

                                 #   -s malloc

                                 #   -s file [default: use /tmp]

                                 #   -s file,<dir_or_file>

                                 #   -s file,<dir_or_file>,<size>

                                 #   -sfile,<dir_or_file>,<size>,<granularity>

    -S secret-file               # Secret file for CLIauthentication

    -T address:port              # Telnet listen address and port

 

]#rpm -ql varnish  

/etc/rc.d/init.d/varnish

/etc/rc.d/init.d/varnishlog

/etc/rc.d/init.d/varnishncsa

/etc/sysconfig/varnish

/etc/varnish

/etc/varnish/default.vcl

/usr/bin/varnishadm

/usr/bin/varnishhist

/usr/bin/varnishlog

/usr/bin/varnishncsa

/usr/bin/varnishreplay

/usr/bin/varnishsizes

/usr/bin/varnishstat

/usr/bin/varnishtest

/usr/bin/varnishtop

/usr/sbin/varnish_reload_vcl

/usr/sbin/varnishd

/usr/share/doc/varnish-2.1.5

……

 

注:

centos7中:

epel源的varnish4.0.3

通过systemctl控制应用启动和关闭;

/etc/varnish/varnish.params,用于在启动varnish时传递运行的参数,不通过此文件则要在命令行中指定;

/usr/lib/systemd/system/varnish.service中定义EnvironmentFile=/etc/varnish/varnish.params,通过定义EnvironmentFile方式加载参数,没有脚本了;

ExecStart=/usr/sbin/varnishd

centos6中:

epel源的varnish2.1.5

/etc/sysconfig/varnish,大多数程序是通过脚本传递参数;

 

]#yum -y install httpd

]#for i in {1..10} ; do echo "page $i on web" > /var/www/html/test$i.html ; done

]#chkconfig --list httpd   #centos7#systemctl start httpd.service#systemctl enable httpd.service#systemctl is-enabled httpd.service

]#/etc/init.d/httpd start

]#ss -tnl | grep :80

LISTEN     0     511                     :::80                      :::*  

 

]#vim /etc/sysconfig/varnish   #(或/etc/sysconfig/varnish不动,更改/etc/varnish/default.vcl中的backend_default {

backenddefault {

  .host = "127.0.0.1";

  .port = "80";

}

);

VARNISH_TTL=120   #varnish连接backend servertimeout

DAEMON_OPTS="-a:6081 \

             -T localhost:6082 \

             -b localhost:80 \

             -u varnish -g varnish \

             -sfile,/var/lib/varnish/varnish_storage.bin,1G"

#DAEMON_OPTS="-a${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \

#             -f ${VARNISH_VCL_CONF} \

#             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT}\

#             -t ${VARNISH_TTL} \

#             -w${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \

#             -u varnish -g varnish \

#             -S ${VARNISH_SECRET_FILE} \

#             -s ${VARNISH_STORAGE}"

 

]#/etc/init.d/varnish restart

Stoppingvarnish HTTP accelerator:                         [  OK  ]

Startingvarnish HTTP accelerator:                         [  OK  ]

]#ss -tnl | egrep "6081|6082"

LISTEN     0     1024                     :::6081                    :::*    

LISTEN     0     1024                     *:6081                     *:*    

LISTEN     0     10               127.0.0.1:6082                    *:*    

LISTEN     0     10                      ::1:6082                    :::*  

 

wKioL1lfPw_gaD1NAAAsaLSwl_o577.jpg

 

]#varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082   #(管理接口)

help

200377    

help[command]

ping[timestamp]   #(查看主机状态)

authresponse

quit

banner

status   #(查看child进程状态)

start   #start,stop用于启停child进程)

stop

stats

vcl.load <configname> <filename>   #(装载vcl文件并编译,configname是自定义的)

vcl.inline <configname> <quoted_VCLstring>

vcl.use <configname>

vcl.discard <configname>

vcl.list

vcl.show <configname>

param.show [-l] [<param>]

param.set <param> <value>

purge.url <regexp>

purge<field> <operator> <arg> [&& <field><oper> <arg>]...

purge.list

 

ping

20019     

PONG1497921153 1.0

 

status

20022     

Childin state running

 

vcl.list   #active为当前在用)

20023     

active          2 boot

 

vcl.load test /etc/varnish/default.vcl

20013     

VCLcompiled.

 

vcl.use test

2000      

 

vcl.list

20046     

available       1 boot

active          1 test

 

vcl.useboot

2000      

 

vcl.list

20046     

active          2 boot

available       0 test

 

vcl.discard test

2000      

 

vcl.list

20023     

active          2 boot

 

param.show   #(显示运行时参数,常用的有:thread_pool_min,thread_pool_max,thread_pools,该server的并发连接数为thread_pools*thread_pool_max;若不想让这些运行时参数被更改,可在启动时用-r指明是只读,

2002413   

acceptor_sleep_decay       0.900000 []

acceptor_sleep_incr        0.001000 [s]

acceptor_sleep_max         0.050000 [s]

auto_restart               on [bool]

ban_lurker_sleep           0.000000 [s]

between_bytes_timeout      60.000000 [s]

cache_vbe_conns            off [bool]

cc_command                 "exec cc -fpic -shared-Wl,-x -o %o %s"

cli_buffer                 8192 [bytes]

cli_timeout                10 [seconds]

clock_skew                 10 [s]

connect_timeout            0.400000 [s]

critbit_cooloff            180.000000 [s]

default_grace              10 [seconds]

default_ttl                120 [seconds]

diag_bitmap                0x0 [bitmap]

err_ttl                    0 [seconds]

esi_syntax                 0 [bitmap]

expiry_sleep               1.000000 [seconds]

fetch_chunksize            128 [kilobytes]

first_byte_timeout         60.000000 [s]

group                      varnish (498)

http_headers               64 [header lines]

http_range_support         off [bool]

listen_address             :6081

listen_depth               1024 [connections]

log_hashstring             off [bool]

log_local_address          off [bool]

lru_interval               2 [seconds]

max_esi_includes           5 [includes]

max_restarts               4 [restarts]

overflow_max               100 [%]

ping_interval              3 [seconds]

pipe_timeout               60 [seconds]

prefer_ipv6                off [bool]

purge_dups                 on [bool]

rush_exponent              3 [requests per request]

saintmode_threshold        10 [objects]

send_timeout               600 [seconds]

sess_timeout               5 [seconds]

sess_workspace             65536 [bytes]

session_linger             50 [ms]

session_max                100000 [sessions]

shm_reclen                 255 [bytes]

shm_workspace              8192 [bytes]

syslog_cli_traffic         on [bool]

thread_pool_add_delay      20 [milliseconds]

thread_pool_add_threshold  2 [requests]

thread_pool_fail_delay     200 [milliseconds]

thread_pool_max            1000 [threads]

thread_pool_min            1 [threads]

thread_pool_purge_delay    1000 [milliseconds]

thread_pool_stack          unlimited [bytes]

thread_pool_timeout        120 [seconds]

thread_pools               2 [pools]

thread_stats_rate          10 [requests]

user                       varnish (498)

vcl_trace                  off [bool]

waiter                     default (epoll, poll)

 

param.show -l   #(显示更详细的信息)

……

 

param.show thread_pools

2001111   

thread_pools               2 [pools]

                           Default is 2

                           Number of workerthread pools.

                          

                           Increasing number ofworker pools decreases lock

                           contention.

                          

                           Too many pools wasteCPU and RAM resources, and

                           more than one poolfor each CPU is probably

                           detrimal to performance.

                          

                           Can be increased onthe fly, but decreases require

                           a restart to takeeffect.

                          

                           NB: This parameter may take quite sometime to

                           take (full) effect.

                          

                           NB: We do not knowyet if it is a good idea to

                           change thisparameter, or if the default value is

                           even sensible.  Caution is advised, and feedback

                           is most welcome.

 

vcl.show boot   #(显示vcl文件编译前的内容)

 

注:

4版本的管理命令行下还有:

panic.show

storage.list

backend.list

backend.set_healthbackend server从离线-->上线);

ban.list(清理缓存中的缓存对象,根据表达式清理某一类缓存对象,默认缓存对象过期则会清理);

 

 

]#varnishlog   #log有关,在宿主机上访问http://10.230.32.208:6081/test6.html[-i tag] [-I regexp] (include regular express); [-X regexp](exclude regular express) [-x tag]

   13 SessionOpen  c 192.168.2.14 2665 :6081

   13 ReqStart     c 192.168.2.14 2665 1994176375

   13 RxRequest    c GET

   13 RxURL        c /test6.html

   13 RxProtocol   c HTTP/1.1

   13 RxHeader     c Host: 10.230.32.208:6081

   13 RxHeader     c Connection: keep-alive

   13 RxHeader     c Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

   13 RxHeader     c User-Agent: Mozilla/5.0 (Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36

   13 RxHeader     c Accept-Encoding: gzip,deflate,sdch

   13 RxHeader     c Accept-Language: zh-CN,zh;q=0.8

   13 VCL_call     c recv

   13 VCL_return   c lookup

   13 VCL_call     c hash

   13 VCL_return   c hash

   13 VCL_call     c miss

   13 VCL_return   c fetch

   14 BackendOpen  b default 127.0.0.1 45242 127.0.0.1 80

   13 Backend      c 14 default default

   14 TxRequest    b GET

   14 TxURL        b /test6.html

   14 TxProtocol   b HTTP/1.1

   14 TxHeader     b Host: 10.230.32.208:6081

   14 TxHeader     b Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

   14 TxHeader     b User-Agent: Mozilla/5.0 (Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36

……

 

]#varnishncsa   #log有关,与combined接近,访问http://10.230.32.208:6081/test8.html

192.168.2.14- - [07/Jul/2017:10:01:19 +0800] "GEThttp://10.230.32.208:6081/favicon.ico HTTP/1.1" 404 290 "-""Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/28.0.1500.72 Safari/537.36"

192.168.2.14- - [07/Jul/2017:10:01:19 +0800] "GEThttp://10.230.32.208:6081/favicon.ico HTTP/1.1" 404 290 "-""Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/28.0.1500.72 Safari/537.36"

 

]#varnishtop   #top

 

]#varnishstat   #statistics,)

]#varnishstat -l   #-l  # Lists the available fields to use with the-f option

Varnishstat-f option fields:

Fieldname           Description

----------           -----------

client_conn          Client connections accepted

client_drop          Connection dropped, no sess/wrk

client_req           Client requests received

cache_hit            Cachehits

cache_hitpass        Cache hits for pass

cache_miss           Cache misses

backend_conn         Backend conn. success

backend_unhealthy    Backend conn. not attempted

backend_busy         Backend conn. too many

backend_fail         Backend conn. failures

backend_reuse        Backend conn. reuses

backend_toolate      Backend conn. was closed

backend_recycle      Backend conn. recycles

backend_unused      Backend conn. unused

fetch_head           Fetch head

fetch_length         Fetch with Length

fetch_chunked        Fetch chunked

fetch_eof            Fetch EOF

fetch_bad            Fetch had bad headers

fetch_close          Fetch wanted close

fetch_oldhttp        Fetch pre HTTP/1.1 closed

fetch_zero           Fetch zero len

fetch_failed         Fetch failed

n_sess_mem           N struct sess_mem

n_sess               N struct sess

n_object             N struct object

n_vampireobject      N unresurrected objects

n_objectcore         N struct objectcore

n_objecthead         N struct objecthead

n_smf                N struct smf

n_smf_frag           N small free smf

n_smf_large          N large free smf

n_vbe_conn           N struct vbe_conn

n_wrk                N worker threads

n_wrk_create         N worker threads created

n_wrk_failed         N worker threads not created

n_wrk_max            N worker threads limited

n_wrk_queue          N queued work requests

n_wrk_overflow       N overflowed work requests

n_wrk_drop           N dropped work requests

n_backend            N backends

n_expired            N expired objects

n_lru_nuked          N LRU nuked objects

n_lru_saved          N LRU saved objects

n_lru_moved          N LRU moved objects

n_deathrow           N objects on deathrow

losthdr              HTTP header overflows

n_objsendfile        Objects sent with sendfile

n_objwrite           Objects sent with write

n_objoverflow        Objects overflowing workspace

s_sess               Total Sessions

s_req                Total Requests

s_pipe               Total pipe

s_pass               Total pass

s_fetch              Total fetch

s_hdrbytes           Total header bytes

s_bodybytes          Total body bytes

sess_closed          Session Closed

sess_pipeline        Session Pipeline

sess_readahead       Session Read Ahead

sess_linger          Session Linger

sess_herd            Session herd

shm_records          SHM records

shm_writes           SHM writes

shm_flushes          SHM flushes due to overflow

shm_cont             SHM MTX contention

shm_cycles           SHM cycles through buffer

sm_nreq              allocator requests

sm_nobj              outstanding allocations

sm_balloc            bytes allocated

sm_bfree             bytes free

sma_nreq             SMA allocator requests

sma_nobj             SMA outstanding allocations

sma_nbytes           SMA outstanding bytes

sma_balloc           SMA bytes allocated

sma_bfree            SMA bytes free

sms_nreq             SMS allocator requests

sms_nobj             SMS outstanding allocations

sms_nbytes           SMS outstanding bytes

sms_balloc           SMS bytes allocated

sms_bfree            SMS bytes freed

backend_req          Backend requests made

n_vcl                N vcl total

n_vcl_avail          N vcl available

n_vcl_discard        N vcl discarded

n_purge              N total active purges

n_purge_add          N new purges added

n_purge_retire       N old purges deleted

n_purge_obj_test     N objects tested

n_purge_re_test      N regexps tested against

n_purge_dups         N duplicate purges removed

hcb_nolock           HCB Lookups without lock

hcb_lock             HCB Lookups with lock

hcb_insert           HCB Inserts

esi_parse            Objects ESI parsed (unlock)

esi_errors           ESI parse errors (unlock)

accept_fail          Accept failures

client_drop_late     Connection dropped late

uptime               Client uptime

backend_retry        Backend conn. retry

dir_dns_lookups      DNS director lookups

dir_dns_failed       DNS director failed lookups

dir_dns_hit          DNS director cached lookups hit

dir_dns_cache_full   DNS director full dnscache

fetch_1xx            Fetch no body (1xx)

fetch_204            Fetch no body (204)

fetch_304            Fetch no body (304)

]#varnishstat -f cache_hit   #-f field_list # Comma separatedlist of fields to display.

 

 

vcl state engine

wKioL1lfPzKQosntAAC1tc8aZ28199.jpg

 

vcl_recv

vcl_hash

vcl_hit,vcl_miss

vcl_fetch

vcl_deliver

vcl_pipe   #当检测到client请求不是gethead时,也不是正常http的方法,用vcl_pipe直接扔给backend server,一手托两家;

vcl_pass

vcl_error   # varnish在前端生成错误页面信息,用于refuse request或其它异常状态由varnish合成错误页面);

Verion4还有:

vcl_purge

vcl_backend_fetch

vcl_backend_response

vcl_synth

vcl_backend_error

 

注:

iptables

prerouting-->input-->forwar-->postrouting

output-->postrouting

 

各引擎间有一定程度的相关性,前一个engine若有多个下游engine,则上游engine需用return指明要转移的下游engine

 

the vcl finite state machine

1comment//,#,/*……*/,这些注释信息可被编译器忽略;

2sub $NAME { },用于定义子例程;

3、不支持循环;

4、有众多内置的变量,变量的可调用位置与state engine有密切相关性;

5、支持终止语句,return (action),没有返回值;

6、“域”专用;

7、操作符,=,==,~,!,&&,||

 

条件判断语句:

if (CONDITION) {

} else {

}

 

变量赋值:

set name=value

unset name=value

 

wKiom1lfP07iOiF4AABkHkbRGcQ354.jpg

 

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;

         }

}

if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "DELETE") {

         return (pipe);

}

if (req.request != "GET" && req.request != "HEAD") {

         return (pass);

}

if (req.http.Authorization || req.http.Cookie) {

         return (pass);

}

return (lookup);

 

hash_data (req.url);

if (req.http.host) {

         hash_data(req.http.host);

} else {

         hash_data(server.ip);

}

return (hash);

 

return (deliver);

 

return (fetch);

 

if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {

         set beresp.ttl = 120 s;

         return (hit_for_pass);

}

return (deliver);

 

state engine workflow(V3)

workflow1:

vcl_recv-->vcl_hash-->vcl_hit->vcl_deliver

wKiom1lfP2KAQew1AAAmgc1ftB4394.jpg

 

workflow2:

vcl_recv-->vcl_hash-->vcl_miss-->vcl_fetch-->vcl_deliverwKiom1lfP3Dx-UlxAAA1diwBHIU004.jpg

 

workflow3:

vcl_recv-->vcl_pass-->vcl_fetch-->vcl_deliver

wKioL1lfP36DZcJzAAA3KsOwSMM457.jpg

 

workflow4:

vcl_recv-->vcl_pipe

wKiom1lfP4yg_FijAAAkXIPUMTk716.jpg

 

variable availability in VCL:

varnish中的内置变量:

req   #req.http.HEADERreq.methodreq.protoreq.urlreq.ttl

resp   #resp.http.HEADERresp.protoresp.reasonresp.status

bereq   #backendbereq.http.HEADERSvarnish发往backend server请求报文的指定首部;bereq.request请求方法;bereq.urlbereq.protobereq.backend指明要调用的后端主机;

beresp   #beresp.protbackendserver响应时的协议版本;beresp.status响应状态码;beresp.reason原因短语;beresp.backend.ipberesp.backend.nameberesp.http.HEADERbackend server响应的报文首部;beresp.ttlbackend server响应的内容余下的生存时长;

client

now

obj   #obj.ttl,对象的ttl值;obj.hits,此对象从缓存中命中的次数;

server   #server.hostnameserver.ip

storage   #storage.<name>.free_spacestorage.<name>.used_spacestorage.<name>.happyhealth status);

functions

wKioL1lfP6Lj2WskAADifIl4mb4986.jpg

 

 

default.vclbackend server定义:

backend NAME {

         .ATTRIBUTE = "VALUE";

         .host = "IP_ADDRESS";

         .port = "PORT";

         .probe = {

                   .url ="/test1.html";

         }

}

 

注:

.probebe作健康状态检测:

probe NAME {

         .ATTRIBUTE = "VALUE";

         .url = "/test.html";

         .expected_response = 200;   #期望的响应状态码,默认200

}

举例:

backend websrv1 {

         .host = "192.168.239.20";

         .port = "80";

         .probe = {

                   .url = "/test.html";

         }

}

backend websrv2 {

         .host = "192.168.239.21";

         .port = "80";

         .probe = {

                   .url = "/test.html";

         }

}

sub vcl_recv{

         if (req.url ~ "(?i)\.(jpg|png|gif)$") {

                   set req.backend_hint = websrv1;

         } else {

                   set req.backend_hint = websrv2;

         }

}

 

LB算法:

fallback

random

round_robin   #是对整个资源轮循,如依次请求/test1.html,/test2.html,/test3.html,若始终访问/test1.html,则始终从一个backend server返回;

hash;

举例:

backend websrv1 {

……

}

backend websrv2 {

……

}

import directors;

sub vcl_init {

         new mycluster = directors.round_robin();

         mycluster.add_backend(websrv1);

         mycluster.add_backend(websrv2);

}

subvcl_recv {

         set req.backend_hint = mycluster.backend();

}

 

注:

#man vmod_directors

#curl http://VARNISH_SERVER:6082/test{1,2,3}.html

 

 

 

例:

给响应给client的报文添加自定义首部X-Cache,在vcl_deliver中定义:

subvcl_deliver {

        if (obj.hits > 0) {

                set resp.http.X-Cache = "HIT from + server.ip";

        } else {

                set resp.http.X-Cache = "MISS";

        }

}

 

vcl.list

20023     

active          1 boot

 

vcl.load test /etc/varnish/test.vcl

20013     

VCLcompiled.

vcl.usetest

2000      

 

wKiom1lfP7Xj79PXAAExje9JcKQ046.jpg

wKioL1lfP8Ox8uP-AAEw9UwaJnk003.jpg

 

例:

varnish支持后端多个虚拟主机:

sub vcl_recv {

         if (req.http.host ~ "www.magedu.com" {

         }

}

 

例:

强制对某资源(或后台登录)的请求,不检查缓存,直接找backend server

sub vcl_recv {

         if (req.url ~ "^/test2.html$"{

                   return (pass);

         if (req.url ~ "(?i)^/login" || req.url ~ "(?i)^/admin") {

                   return (pass);

}

 

例:

对特定类型的资源取消其私有的cookie标识,并强行设定其可以varnish缓存时长:

sub vcl_babckend_response {

         if (beresp.http.cache-control !~ "s-maxage") {

                   if (bereq.url ~ "(?i)\.jpg$") {

                            set beresp.ttl = 3600s;

                            unset beresp.http.Set-Cookie;

                   }

         if (bereq.url ~ "(?i)\.css$"){

                   set beresp.ttl = 600s;

                   unset beresp.http.Set-Cookie;

         }

}

 

 

 

 



一、相关概念:

http/1.0-->http/1.1(重大改进:对缓存功能实现了更精细化的设计)

RFCrequest file comment,每一种协议都有请求注解文档,讲协议规范)

http页面由众多的web object组成,有些是静态,有些是通过程序执行后生成的;为加速web的访问,browser中引入了缓存机制,能将访问的静态内容或可缓存的动态内容缓存到本地,而后client再次到原始server上请求之前相同的内容时,如果原始server上的内容没发生改变,就直接使用本地已缓存的数据,而非从原始server上再次下载,这整个过程是如何完成的,http是如何支持缓存机制的(server上的缓存,并非所有内容都能缓存,如登录时的账号密码、向用户返回的cookie,缓存有失效时间)

 

缓存的类型:

public cache(如nginxvarnish

private cache(用户browser的本地缓存,一般用户本地的缓存是安全的,但若这个电脑是公共部门的,很多人使用,相对来说也不安全)

 

一般能缓存的前提是原始server上的内容没发生改变的,client怎么知道他请求的内容在自己本地缓存中有没失效,从而不用去原始server上获取数据,解决方案:

1)服务器在第一次响应用户的请求时,在http首部中明确告诉client此资源可以缓存的有效时长为10min,使用expires指明过期时间,如Expires: Fri , 12 May 2006 18:53:33 GMT

2server将数据响应给client时没设置缓存期限,但client觉得这是个静态内容可以缓存(client自己设置了一些缓存策略,如只要是静态内容我就缓存),缓存下来之后并不知道远程server中是否改变,当再次请求之前请求的内容时,告诉server我这存的有一份它的上一次修改时间是什么时候,server一对比发现同一对象的修改时间一致,由此可知server上的内容没改变,于是serverclient响应码304Not Modified),告诉client此前内容没改变你可以继续使用,于是clientbrowser直接整合本地缓存的资源得以显示

 

以上是基于时间来实现缓存机制控制的(http/1.0的缓存机制是靠prog来标记能否缓存,并使用Expires定义某资源到什么时候过期);http/1.1 对缓存机制引入了很多首部,有些首部专用于client,有些首部专用于server,让双方基于某种功能进行协商,判定缓存对象是否能进一步使用的机制)

 

缓存相关的http首部:

1Expires(绝对时间计时法,绝对日期时间,GMT格式,如Expires: Fri , 12 May 2006 18:53:33 GMT,它返回给client的时间是明确的时间,clientbrowser缓存了这个资源后,若再次发起请求同样内容时,只要在这个时间内就不去server请求了直接从本地取,Expires的缺陷(若clientserver上的时间不一致就无法比较了),这种机制在http/1.0上常用,而在http/1.1上使用时长来定义max-age

2cache-control中的max-agemax-agehttp/1.1中使用,用于定义时长,明确告诉client某个资源可缓存多长时间,从server发送这个资源开始倒计时,只要倒计时结束,缓存资源立即失效,如Cache-Control:max-age=600

注:如果既指定Expires又在cache-control中指定max-age,那Expires的设定将被忽略

注:cache-controlhttp中重要的首部,用于定义所有的缓存机制都必须遵循缓存指示,无论时间有无过期或有没有给最长缓存时间都要接受cache-control的控制,就算某个资源定义可缓存两天,但同时又使用了cache-control指令告诉你不能进行缓存,那结果就是不能缓存,指令包括有:publicprivateno-cacheno-storemax-ages-maxagemust-reval-idate

public(放在public cache上,所有人都能获取,不涉及隐私泄露)

private(只能缓存在用户的私有缓存区域,像nginxvarnish这样的public cache server是不能缓存的)

no-cache(表示可以缓存,但每次都要向server发起原始资源验证,没有标记no-cache时只要在过期时间内,直接从本地获取不用向server验证这个资源能否用,而标记了no-cache不论在不在过期时间内都要向server验证)

s-maxage(主要控制私有缓存的过期期限)

3Etag(响应首部,某些站点,数据变化频率很高,如client1s里发起好几次请求index.html这个资源(Expires:Fri , 12 May2006 18:53:33 GMT),但在server1s内更新了好几次页面(主页动态生成),对于这个对象clientserver时间的比较结果还是之前的时间,但实际server上的资源已经改变了,所以时间戳这种方法过于粗糙,这种按秒计时不足以描述页面文件的变化频率,有可能让已失效的缓存继续使用,因此引入Etagextended tag扩展标记,给页面定义版本号(版本号是随机生成的,每次生成一个页面都会自动加版本号),Etag是个响应首部,用于在响应报文中为某web资源定义版本标识符,这样client过来验证不是基于时间戳而是对比Etag,就算更新频率在秒级以下也能验证资源是否发生改变)

注:(1)(2)都是绝对判定法,http/1.1引入条件判断,每次验证资源时是向server发起询问条件,如Last-ModifiedIf-Modified-Since

4Last-Modified(响应首部,某资源在server上最后修改的时间,当client第一次请求某资源时,server返回状态200,内容是client请求的内容,同时有Last-Modified属性标记此文件在server上最后被修改的时间,如Last-Modified : Fri , 12 May 2006 18:53:33 GMT

5If-Modified-Since(条件式请求首部,当client第二次请求相同的内容时询问server此对象Last-Modified是否发生了改变,若没改变server响应给client304Not Modified),若改变了则响应改变的内容与第一次请求类似,从而保证不向client重复发出资源,也保证当server有变化时client能得到最新的资源)

6If-None-Match(条件式请求首部,这是个否定请求,clinet第二次请求相同内容时会询问server之前发的某个资源的Etag是否不匹配,server若回答是则不匹配,响应新资源,若server回答否则client使用之前的缓存)

注:If-Modified-SinceLast-Modified有关,If-None-MatchEtag有关,这整个过程:

client请求一个页面A

server返回页面A,并给A加上Last-ModifiedEtag

client展示页面A,并将页面和Last-ModifiedEtag一同缓存;

client再次请求页面A,将Last-ModifiedEtag一同传给server(在首部使用If-Modified-SinceIf-None-Match分别询问Last-ModifiedEtag是否修改);

server检查Last-ModifiedEtag判断出是否修改,若未修改则响应304和一个空的响应体

7Vary(响应首部,原始server根据请求来源的不同响应不同的首部,Vary通知缓存机制client获取页面是如何得到页面的,常用的有:Vary:Accept-Encodingclient若支持压缩功能在请求时将请求报文压缩,那server在响应时也使用压缩返回,Vary根据client的编码机制(文本或gzip压缩或deflate压缩)server采用相应的机制返回)

8Age(缓存server可发送一个额外的响应首部,用于指定响应的有效期限,browser通常根据此首部决定内容的缓存时长,如果响应报文首部还使用了max-age指令,那缓存的有效时长为max-age减去Age的结果)

 

假设我们的reverse proxy上提供缓存,后端是RS(原始server),clientreverse proxy请求某页面,reverse proxy中有该页面的缓存则直接响应给clientclient于是在本地缓存),若reverse proxy中没该页面的缓存,则reverse proxy向原始server发起请求,原始server响应资源给reverse proxy,同时一并给一个首部,如Cache-Control:max-age=600reverse proxy将资源缓存下来在600s内都有效,reverse proxy于是重新构建首部并响应给clientreverse proxy构建首部时可以自定义告诉client什么时候过期,如告诉client可以缓存1年,也可告诉client缓存1min),假设reverse proxyclient的过期时长是1min,当同一client再次请求同样内容时(若在缓存过期时间内(1min内)则从本地缓存中直接取;若过了过期时间(1minclient不会立即清除缓存,而是使用条件式请求首部请求,reverse proxy比较两次时间,若时间一样则向client返回304reverse proxy于是再给client一个缓存过期时间(1min),所以就算过了过期时间也不一定从reverse proxy上重复获取数据;若是强制刷新ctrl+F5则仍会到reverse proxy上请求)

client在第11min时reverse proxy请求同一页面,reverse proxy发现本地缓存已失效(reverse proxy不会使用已失效内容响应的),它向原始server发起条件式请求(If-Modified-SinceIf-None-Match),若原始server发现没修改则返回304Not Modified),这样reverse proxy的本地缓存时间就更新了,于是使用本地缓存响应给client

 

举例:

第一次请求时:

wKiom1aoft6hKCB-AACqVormCRg400.jpg

再次刷新后:

wKioL1aofzPQ4SyNAACpVDI9HkU057.jpg

 

 

cache server并不是缓存任意数据(不允许缓存某些数据),如不能缓存用户的cookie信息,如果用户请求的内容中有变化的cookie信息的话,缓存是命中不了的,缓存中是key:value,若key中包含经常变化的内容,命中率是很低的,很多时候缓存时都把cookie信息去掉,以提高命中率;不能缓存某些动态生成的资源,如表单中填入的账号密码;若请求方法是PUTPOST写操作,也不能缓存,一般缓存的都是GET操作的数据(就算是GET操作若包含用户的认证授权类信息也不能缓存)

 

可在cache server上自定义缓存策略(把某些资源根据我们自己的理解从原始server上剥离出来自己定义这些资源的缓存时间),如cache server到原始server上请求数据,若请求的是站点的LOGO图片,虽原始server告诉cache server可缓存10min,但cache server(管理者)觉得该内容是静态的而且很长时间都不会变,于是cache server响应时告诉client可缓存半年,client在自己本地私有缓存中保存的内容越多,那向server发起请求的或获取的数据就越少,资源发送少了,带宽占用率就小了,client从本地缓存直接拿数据会很快,这样用户体验度就好

 

 cache server放到离client越近越好(最好放在家门口),尽量将资源丢到用户的缓存中,我们电脑上或手机上使用时间长了会缓存一些数据,这样使得上网速度更快并节省流量,某些软件会提示清理垃圾,若清理了下次请求将占用带宽重新获取

 

缓存扩展结构:CDNcache delivery network,内容分发网络),如图:

clientserver这之间可定义N层缓存(ncache servercache server之间是分层次的),client请求到cache server11号发现自己没有要响应的内容时它不会去找原始server,它会先找它的兄弟服务器(cache server22若没有再去找它的父cache server33没有找它的父cache server4,父cache server中没有,由父缓存找原始server12是兄弟服务器(sibling),31的父(parent),43的父),这些cache server之间通过内容缓存协议且能共享缓存对象共同组成的网络叫CDN,由此client请求时在中间这个网络上就可取得所有内容,同时这些cache server可定义一些策略,如定期到原始server上获取数据无论client有无请求

wKiom1aofwCApLpsAAAl5ESLgoU506.jpg

为使用户体验好同时又减轻server压力使用CDN,如下图四个区域组成的CDN

未用CDN前,DNS解析:www.magedu.com  in A  1.1.1.1

使用CDNDNS要解析成别名,指向cache server上的某一个,如指向杭州CDN节点(www.magedu.com  in CNAME  hz.cdn.com),这样杭州用户访问会很快,其它区域的用户访问还是很慢,用智能DNS解决(根据client来源判定它属于哪个区域网络,于是DNS解析时不是四个都返回,而是仅返回离它最近最快的那个cache server的域名)

智能DNS+CDN这才是真正意义的CDN,当client请求时由该区域的CDN节点响应内容,若该节点没相应内容,它不去找源站而是找离它近的节点,兄弟服务器和父服务器都没有才找源站

wKioL1aof1az6UaKAAAx4v8NPhU058.jpg

 

这些cache server能根据内容缓存协议来实现缓存对象共享,高级CDN还能实现内容路由(某个cache server上没有内容时自动找有内容的cache server),使得尽可能不去找原始server,这并不能完全避免找原始server(如动态内容),就算缓存的内容是静态的,也不会把整站的内容都缓存上去,只能缓存一部分,若缓存策略定义的好,将站点的热区数据都拉到cache server上实现尽可能多的在cache server上缓存

CDN通常是按流量收费,视频站点和图片站点都要用CDN否则流量大了很容易垮掉

对于中小型电子商务站点可自建CDN,前提要使用智能DNS(可自建智能DNS,也可使用公共的智能DNS serverdnspod

注:dnspod在防DDOS方面很强,每秒解析达到数百万,还可达到秒级的更新,更新后随时生效,还有监控原始server的功能,原始server还可通过它做LB完成health check

DNS本身也要分区域(如北方电信、南方联通等),访问网站不只是获取网页的时间还有DNS解析返回,再请求资源,若DNS很慢也影响用户体验

bind dlz+{mysql,pgsql,oracke,DB4}http://bind-dlz.sourceforge.net/,将用户的资源放到数据库中会很慢,如果不是做公共dns server仅为自己公司解析可放在file中,dns启动时会直接加载至内存中;一般使用bind即可(bind本身就提供了智能解析(view)

注:DB4,基于hash编码的数据库

 

varnishhttps://www.varnish-cache.org/):

互联网早期的cache serversquid(乌贼,章鱼,八爪鱼)

varnish本身是reverse proxy server同时又提供cache功能,配置简单、接口简单、监控接口丰富,由于采用新架构设计,之后扩展要比squid容易,功能与nginx近似,但varnish在创建连接、维持连接的能力比nginx差远了,通常使用nginx+varnishnginx处理连接,varnish专门负责缓存),也可nginx+squidsquid功能很强大,支持正向代理、反向代理、ACL、支持内容分发协议,特性非常丰富,配置复杂)

varnish尽可能利用时下最新的技术,时下最好的软件设计结构,时下安全体系的诸多经验,站在前人的基础上设计的,但squid也宝刀未老,早期淘宝在前端的cache server就使用100多台server创建的squid cache cluster,优化后的命中率达到97%(纯静态内容),做到这地步要对站点的静态资源做好筛选(要将哪些内容放到cache server上)

squid VS  varnish(同httpd  VS nginx

 

 

varnish architecture(与nginx类似,是master/slave架构):

主进程(管理进程management,负责配置文件分析、装载新配置文件、启动子进程;Management进程主要实现应用新的配置(若检测到VCL配置文件有语法错误则拒绝编译,避免子进程加载错误配置导致缓存崩溃)、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程):

CLI interface(通过命令行接口与命令行的控制指令进行交互)

telnet interface(为安全这种方式已很少用,可用专用的client工具varnishadm连到管理进程完成启动停止等)

web interfaceGUI接口)

 

子进程(child|cache进程,child提供服务、发送至后端并响应用户请求;cache缓存管理的进程,缓存清理、缓存有效期限检查等):

command line

storage/hashing(存储缓存,用key定义查找标准,将key放在某个backet中实现O(1)的查找,查找到的内容即是value

log/statsvarnish的日志不是保存在file中,有磁盘IO,而是在内存中,启动服务时就明确说明用多大空间保存日志,空间占完后将覆盖之前的文件继续使用,一圈圈轮着使用,日志记录有client的请求数、client请求命中数、没命中数、server运行多长时间等;可用工具将日志导出查看,如varnishlog等)

accept(接收用户请求并将请求转至workerthreads上)

backend communication(后端主机通信)

worker threads(一个线程响应多个请求,child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多)

object expiry(从缓存中清理过期内容)

wKiom1aofyPhLwtiAABXuAJnyYA567.jpg

 

varnish的主进程management只有一个,child进程由多个不同的线程组成,varnish总体连接数在大于5000时性能会下降,一般不会让工作线程接受太多连接,性能有上限,假设有10varnish server每个平均接受5000个连接,那10个就能接受5W个了,前端nignx已处理一些请求再将多个请求转到varnish server上,这种架构已达到亿级或十亿级PV

 

VCLvarnish configuration language),底层用C开发,完全兼容C语言,提供编程接口,要写程序提供配置文件,用VCL开发程序时指明varnish怎么工作(哪些内容缓存、哪些内容不缓存、哪些内容不通过缓存来取等),为使VCL开发出的程序更加高效,要将其编译为二进制格式(使用VCL编写好配置文件后,使用gcc编译)

配置文件编译完后生成共享模块,child/cache如何工作就取决于共享模块中的定义,二进制格式的配置文件被子进程child/cache读取,child从后端server取得内容后要缓存在本地,由storage/hashing子模块将缓存内容存下来

 

VCL工作在varnish的状态引擎state engine上,在varnish内部有多个state engine(同iptablesnetfilter框架中的几个接口类似(勾子函数),若某个报文不经过这几个勾子函数将检测不到,所以这几个勾子要放在报文必经的路口,使得报文必须要经过这其中1个或几个勾子,在这些勾子上就能实现管理)

如图:椭圆表示state engine(又叫domain),菱形表示检查机制(条件判断)

wKioL1aof3fg4QlhAACFEZJ5a_8968.jpg

vcl_recv(第一个入口的state engine,请求报文接进来)

vcl_recv-->vcl_pass(例如是动态内容或用户的私有内容直接到后端去取)

vcl_recv-->vcl_hash(根据key来查找本地缓存)

vcl_recv-->vcl_pipe(不对client进行检查或做出任何操作,而是在client和后端server之间建立专用pipe,并直接将数据在二者之间传送;keep-alive连接中后续传送的数据也都通过此管道进行直接传送,并不会出现在任何日志中)

vcl_hit-->vcl_deliver(命中后交给vcl_deliver再投递给client

vcl_hit-->vcl_pass(在管理的CLI下,命中后将缓存清除)

vcl_pass(可对三个state enginedomain)过来的报文统一处理(vcl_recvvcl_hitvcl_miss),统一到一个反向操作上(例如命中后不去找缓存而是找vcl_fetch继而找后端server))

vcl_fetch(到这个domain上就要联系后端server,这个域上会定义一些语句来判定哪些内容缓存哪些不缓存(如authcookie有关的字串就不缓存))

路线:

vcl_recv-->vcl_hash-->vcl_hit-->vcl_deliver

vcl_recv-->vcl_hash-->vcl_miss-->vcl_fetch-->vcl_deliver

vcl_recv-->vcl_pass-->vcl_fetch-->vcl_vcl_deliver

 

每个state engine中定义一堆条件判断(如定义vcl_recv在什么情况下去找vcl_hash,在什么情况下找vcl_pass,例如某些client不允许访问、某些client查找哪些资源、哪些资源不允许缓存等,通过定义各种条件判断指挥着到下一个数据流或state engine

每个state engine又被叫作domain,每个domain都有可执行的指令(如netfilter上各种链上的规则,每个链所接受的规则是不一样的,处理完成有可能还要经过下个链,有可能直接返回),而对varnish的每个state engine都要走向下一步(除vcl_deliver

VCL编程,所写的代码,只对当前state engine生效(可理解为函数,函数执行完有返回值),返回的是什么就决定下一步怎么走,若return返回hash就找vcl_hash,若return pass则找vcl_pass,到底返回哪个要做写一大堆的if语句做出判断

以上涉及到编程,程序中策略写的好,缓存命中率就高

 

VCL语法:

1)注释:///*(单选注释);*/(多行注释)

2sub $name(定义函数,subroutine子例程)

3)不支持循环,有内置变量(内置变量应用位置独特,有的变量应用在前半段(请求报文首部),有的变量应用在后半段(响应报文首部))

4)使用终止语句,没有返回值

5)域专用(每个state engine定义自己的程序)

6)操作符(=赋值、==等值比较、~模式匹配、!&&||

VCL的函数不接受参数且没有返回值,因此并非真正意义的函数,这也限定了VCL内部的数据传递只能隐藏在http首部内部进行,VCLreturn语句用于将控制权从VCL状态引擎返回给varnish,而非默认函数,这就是VCL只有终止语句没有返回值的原因;同时对于每个域来说,可定义一个或多个终止语句,告诉varnish下一步采取何种操作(如查询缓存或不查询缓存等)

 

VCL的内置函数:

regsub(str,regex,sub)

regsuball(str,regex,sub)

以上两项实现替换(substituend,用于将regexp匹配到的str替换为sub,相当于nginxrewrite,而regsuball相当于加了修饰符/g的替换)

ban(expression)

ban_url(regex)

purge

以上三项实现缓存清理,给某个缓存对象设置栅栏,阻止对其使用,先放到禁止列表中再禁止使用,purge仅允许有权限经过认证的管理员使用

hash_data(str)(取得一个字符串的hash值,若这个字符串是缓存中的某个key,则可判定缓存中是否有)

return()(当某个域运行结束时将控制权返回给varnish,并指示下一步的动作,可以返回的指令有:lookup,pass,pipe,hit_for_pass,fetch,deliver,hash等),特定域只能返回特定的指令)

return(restart)(重新运行整个VCL,即从vcl_recv开始进行处理,每一次重启都会增加req.restarts变量中的值,而max_restarts参数则用于限定最大重启次数,例如vcl_recv-->vcl_hash-->vcl_miss-->vcl_pass-->restart-->vcl_recv……,未命中可不让去vcl_fetch,让重启,在vcl_pass中写入regsub(……)url重写rewrite,再在vcl_recv上跑一遍,有可能就命中了,若写了错误的rewrite将导致死循环,restart判定若超过5次就退出直接向client返回error

注:vcl_deliver要能在client请求内容不存在时或restart超过5次退出时,返回错误页面,varnish-server要能生成错误响应页(如404,502等)

 



本文转自 chaijowin 51CTO博客,原文链接:http://blog.51cto.com/jowin/1739282,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论
技术小阿哥
+ 关注