Linux运维 第三阶段 (十八) varnish
Linux運維 第三階段 (十八) varnish
?
數據:
結構化數據,RDBMS;
非結構化數據,FS,存海量小文件,NAS、SAN、DFS可提供較好的性能;
?
web cache:
程序具有局部性(時間局部性;空間局部性);
key-value,key(url訪問路徑,hash),value(web content);
hotpot熱點數據;
命中率=hit/(hit+miss),文檔命中率(從文檔個數進行衡量),字節命中率(從內容大小進行衡量);
緩存對象,有生命周期,定期清理;
緩存空間耗盡,LRU算法;
可緩存,不可緩存(用戶私有數據);
cache is king;
?
緩存的處理步驟:
接收請求-->解析請求(提取請求的URL及各種首部)-->查詢緩存-->新鮮度檢測-->創建響應報文-->發送響應-->記錄日志;
?
新鮮度檢測機制:
過期日期:
http/1.0,Expires,時區不同則有問題;
http/1.1,Cache-Control: max-age=600,該網頁內容最多存活時間,比Expires要好;
有效性再驗證,revalidate:
如果原始內容未改變,則僅響應首部(不附帶body部分),響應碼304(Not Modified);
如果原始內容發生改變,則正常響應,響應碼200;
如果原始內容消失,則響應404,此時緩存中的cache object也應被刪除;
?
條件式請求首部:
If-Modified-Since(基于請求內容的時間戳作驗證);
If-Unmodified-Since;
If-Match;
If-None-Match(Etag);
?
Cache-Control:cache-directive?? #(更加靈活的緩存控制機制)
cache-request-directive請求:
no-cache(不要緩存的實體,要求現在從web server上取);
max-age(只接受Age值小于max-age值,并且沒有過期的對象);
max-stale(可以接受過去的對象,但過期時間必須小于max-stale值);
min-fresh(接受其新鮮生命期大于其當前Age跟min-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上的內容未必發生改變;
?
HTTP validation:
Last-Modified/If-Modified-Since;
Etag/If-None-Match;
?
兩者結合:
you can combie HTTP headers the way you want,Expiration wins over Validation;
?
常見的緩存服務器開源解決方案:
varnish VS squid(類似nginx VS httpd);
?
CDN(GSLB,緩存路由協議;大公司,全國各機房自建CDN;中小公司租用 第三方CDN,帝聯、藍訊等);
?
http://www.varnish-cache.org/
?
varnish architecture:
?
DSL,domain specific language;
VCL,varnish configuration language,緩存策略配置接口,基于域的簡單編程語言;
管理進程(編譯vcl并應用新配置,監控varnish,初始化varnish;CLI接口);
child/cache(acceptor(接收新的連接請求);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在這個文件內部組織出專用的FS,varnish自己識別每一個緩存對象從哪開始到哪結束,名字等元數據,varnish用于緩存的這一單個文件是獨立自治的王國;varnish服務在運行過程中不能隨便重啟,否則緩存全部失效);
注:
nginx將緩存對象放在disk中,key在內存里,nginx緩存在定義時有多級緩存目錄,levels=1:2:2,目錄下放緩存對象,每一個緩存對象用一個文件來存,因此會有很多文件描述符inode;
方式二:malloc(在內存中存放緩存對象,時間久了有內存碎片);
方式三:persistent(基于文件的持久存儲,實驗階段,有io問題,最好用SSD disk);
?
配置varnish的三種接口:
1、varnishd應用程序的命令行參數:
監聽的socket,使用的存儲類型等額外的配置參數;
-p param=value
-r param,param,……?? #(設定只讀參數列表)
2、-p選項指明的參數,run-time運行時參數,可在程序運行時,通過其CLI進行配置;
3、vcl,配置緩存系統的緩存機制,通過vcl配置文件進行配置,先編譯(依賴c compile,gcc),后應用,/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/6082,6081服務端口,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源的varnish是4.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源的varnish是2.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 server的timeout)
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??????????????????? :::*??
?
?
]#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_health(backend 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:
?
vcl_recv;
vcl_hash;
vcl_hit,vcl_miss;
vcl_fetch;
vcl_deliver;
vcl_pipe?? #當檢測到client請求不是get、head時,也不是正常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:
1、comment,//,#,/*……*/,這些注釋信息可被編譯器忽略;
2、sub $NAME { },用于定義子例程;
3、不支持循環;
4、有眾多內置的變量,變量的可調用位置與state engine有密切相關性;
5、支持終止語句,return (action),沒有返回值;
6、“域”專用;
7、操作符,=,==,~,!,&&,||;
?
條件判斷語句:
if (CONDITION) {
} else {
}
?
變量賦值:
set name=value
unset name=value
?
?
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
?
workflow2:
vcl_recv-->vcl_hash-->vcl_miss-->vcl_fetch-->vcl_deliver
?
workflow3:
vcl_recv-->vcl_pass-->vcl_fetch-->vcl_deliver
?
workflow4:
vcl_recv-->vcl_pipe
?
variable availability in VCL:
varnish中的內置變量:
req?? #req.http.HEADER;req.method;req.proto;req.url;req.ttl;
resp?? #resp.http.HEADER;resp.proto;resp.reason;resp.status;
bereq?? #backend;bereq.http.HEADERS由varnish發往backend server請求報文的指定首部;bereq.request請求方法;bereq.url;bereq.proto;bereq.backend指明要調用的后端主機;
beresp?? #beresp.prot,backendserver響應時的協議版本;beresp.status響應狀態碼;beresp.reason原因短語;beresp.backend.ip;beresp.backend.name;beresp.http.HEADER從backend server響應的報文首部;beresp.ttl,backend server響應的內容余下的生存時長;
client
now
obj?? #obj.ttl,對象的ttl值;obj.hits,此對象從緩存中命中的次數;
server?? #server.hostname;server.ip;
storage?? #storage.<name>.free_space;storage.<name>.used_space;storage.<name>.happy(health status);
functions
?
?
default.vcl中backend server定義:
backend NAME {
???????? .ATTRIBUTE = "VALUE";
???????? .host = "IP_ADDRESS";
???????? .port = "PORT";
???????? .probe = {
?????????????????? .url ="/test1.html";
???????? }
}
?
注:
.probe對be作健康狀態檢測:
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??????
?
?
例:
讓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(重大改進:對緩存功能實現了更精細化的設計)
RFC(request file comment,每一種協議都有請求注解文檔,講協議規范)
http頁面由眾多的web object組成,有些是靜態,有些是通過程序執行后生成的;為加速web的訪問,browser中引入了緩存機制,能將訪問的靜態內容或可緩存的動態內容緩存到本地,而后client再次到原始server上請求之前相同的內容時,如果原始server上的內容沒發生改變,就直接使用本地已緩存的數據,而非從原始server上再次下載,這整個過程是如何完成的,http是如何支持緩存機制的(server上的緩存,并非所有內容都能緩存,如登錄時的賬號密碼、向用戶返回的cookie,緩存有失效時間)
?
緩存的類型:
public cache(如nginx,varnish)
private cache(用戶browser的本地緩存,一般用戶本地的緩存是安全的,但若這個電腦是公共部門的,很多人使用,相對來說也不安全)
?
一般能緩存的前提是原始server上的內容沒發生改變的,client怎么知道他請求的內容在自己本地緩存中有沒失效,從而不用去原始server上獲取數據,解決方案:
(1)服務器在第一次響應用戶的請求時,在http首部中明確告訴client此資源可以緩存的有效時長為10min,使用expires指明過期時間,如Expires: Fri , 12 May 2006 18:53:33 GMT;
(2)server將數據響應給client時沒設置緩存期限,但client覺得這是個靜態內容可以緩存(client自己設置了一些緩存策略,如只要是靜態內容我就緩存),緩存下來之后并不知道遠程server中是否改變,當再次請求之前請求的內容時,告訴server我這存的有一份它的上一次修改時間是什么時候,server一對比發現同一對象的修改時間一致,由此可知server上的內容沒改變,于是server給client響應碼304(Not Modified),告訴client此前內容沒改變你可以繼續使用,于是client的browser直接整合本地緩存的資源得以顯示
?
以上是基于時間來實現緩存機制控制的(http/1.0的緩存機制是靠prog來標記能否緩存,并使用Expires定義某資源到什么時候過期);http/1.1?對緩存機制引入了很多首部,有些首部專用于client,有些首部專用于server,讓雙方基于某種功能進行協商,判定緩存對象是否能進一步使用的機制)
?
緩存相關的http首部:
(1)Expires(絕對時間計時法,絕對日期時間,GMT格式,如Expires: Fri , 12 May 2006 18:53:33 GMT,它返回給client的時間是明確的時間,client的browser緩存了這個資源后,若再次發起請求同樣內容時,只要在這個時間內就不去server請求了直接從本地取,Expires的缺陷(若client和server上的時間不一致就無法比較了),這種機制在http/1.0上常用,而在http/1.1上使用時長來定義max-age)
(2)cache-control中的max-age(max-age在http/1.1中使用,用于定義時長,明確告訴client某個資源可緩存多長時間,從server發送這個資源開始倒計時,只要倒計時結束,緩存資源立即失效,如Cache-Control:max-age=600)
注:如果既指定Expires又在cache-control中指定max-age,那Expires的設定將被忽略
注:cache-control是http中重要的首部,用于定義所有的緩存機制都必須遵循緩存指示,無論時間有無過期或有沒有給最長緩存時間都要接受cache-control的控制,就算某個資源定義可緩存兩天,但同時又使用了cache-control指令告訴你不能進行緩存,那結果就是不能緩存,指令包括有:public、private、no-cache、no-store、max-age、s-maxage、must-reval-idate
public(放在public cache上,所有人都能獲取,不涉及隱私泄露)
private(只能緩存在用戶的私有緩存區域,像nginx、varnish這樣的public cache server是不能緩存的)
no-cache(表示可以緩存,但每次都要向server發起原始資源驗證,沒有標記no-cache時只要在過期時間內,直接從本地獲取不用向server驗證這個資源能否用,而標記了no-cache不論在不在過期時間內都要向server驗證)
s-maxage(主要控制私有緩存的過期期限)
(3)Etag(響應首部,某些站點,數據變化頻率很高,如client在1s里發起好幾次請求index.html這個資源(Expires: Fri , 12 May2006 18:53:33 GMT),但在server上1s內更新了好幾次頁面(主頁動態生成),對于這個對象client和server時間的比較結果還是之前的時間,但實際server上的資源已經改變了,所以時間戳這種方法過于粗糙,這種按秒計時不足以描述頁面文件的變化頻率,有可能讓已失效的緩存繼續使用,因此引入Etag,extended tag擴展標記,給頁面定義版本號(版本號是隨機生成的,每次生成一個頁面都會自動加版本號),Etag是個響應首部,用于在響應報文中為某web資源定義版本標識符,這樣client過來驗證不是基于時間戳而是對比Etag,就算更新頻率在秒級以下也能驗證資源是否發生改變)
注:(1)(2)都是絕對判定法,http/1.1引入條件判斷,每次驗證資源時是向server發起詢問條件,如Last-Modified、If-Modified-Since
(4)Last-Modified(響應首部,某資源在server上最后修改的時間,當client第一次請求某資源時,server返回狀態200,內容是client請求的內容,同時有Last-Modified屬性標記此文件在server上最后被修改的時間,如Last-Modified : Fri , 12 May 2006 18:53:33 GMT)
(5)If-Modified-Since(條件式請求首部,當client第二次請求相同的內容時詢問server此對象Last-Modified是否發生了改變,若沒改變server響應給client304(Not Modified),若改變了則響應改變的內容與第一次請求類似,從而保證不向client重復發出資源,也保證當server有變化時client能得到最新的資源)
(6)If-None-Match(條件式請求首部,這是個否定請求,clinet第二次請求相同內容時會詢問server之前發的某個資源的Etag是否不匹配,server若回答是則不匹配,響應新資源,若server回答否則client使用之前的緩存)
注:If-Modified-Since與Last-Modified有關,If-None-Match與Etag有關,這整個過程:
client請求一個頁面A;
server返回頁面A,并給A加上Last-Modified、Etag;
client展示頁面A,并將頁面和Last-Modified、Etag一同緩存;
client再次請求頁面A,將Last-Modified、Etag一同傳給server(在首部使用If-Modified-Since、If-None-Match分別詢問Last-Modified、Etag是否修改);
server檢查Last-Modified、Etag判斷出是否修改,若未修改則響應304和一個空的響應體
(7)Vary(響應首部,原始server根據請求來源的不同響應不同的首部,Vary通知緩存機制client獲取頁面是如何得到頁面的,常用的有:Vary:Accept-Encoding,client若支持壓縮功能在請求時將請求報文壓縮,那server在響應時也使用壓縮返回,Vary根據client的編碼機制(文本或gzip壓縮或deflate壓縮)server采用相應的機制返回)
(8)Age(緩存server可發送一個額外的響應首部,用于指定響應的有效期限,browser通常根據此首部決定內容的緩存時長,如果響應報文首部還使用了max-age指令,那緩存的有效時長為max-age減去Age的結果)
?
假設我們的reverse proxy上提供緩存,后端是RS(原始server),client向reverse proxy請求某頁面,reverse proxy中有該頁面的緩存則直接響應給client(client于是在本地緩存),若reverse proxy中沒該頁面的緩存,則reverse proxy向原始server發起請求,原始server響應資源給reverse proxy,同時一并給一個首部,如Cache-Control:max-age=600,reverse proxy將資源緩存下來在600s內都有效,reverse proxy于是重新構建首部并響應給client(reverse proxy構建首部時可以自定義告訴client什么時候過期,如告訴client可以緩存1年,也可告訴client緩存1min),假設reverse proxy給client的過期時長是1min,當同一client再次請求同樣內容時(若在緩存過期時間內(1min內)則從本地緩存中直接取;若過了過期時間(1min)client不會立即清除緩存,而是使用條件式請求首部請求,reverse proxy比較兩次時間,若時間一樣則向client返回304,reverse proxy于是再給client一個緩存過期時間(1min),所以就算過了過期時間也不一定從reverse proxy上重復獲取數據;若是強制刷新ctrl+F5則仍會到reverse proxy上請求)
若client在第11min時向reverse proxy請求同一頁面,reverse proxy發現本地緩存已失效(reverse proxy不會使用已失效內容響應的),它向原始server發起條件式請求(If-Modified-Since、If-None-Match),若原始server發現沒修改則返回304(Not Modified),這樣reverse proxy的本地緩存時間就更新了,于是使用本地緩存響應給client
?
舉例:
第一次請求時:
再次刷新后:
?
?
cache server并不是緩存任意數據(不允許緩存某些數據),如不能緩存用戶的cookie信息,如果用戶請求的內容中有變化的cookie信息的話,緩存是命中不了的,緩存中是key:value,若key中包含經常變化的內容,命中率是很低的,很多時候緩存時都把cookie信息去掉,以提高命中率;不能緩存某些動態生成的資源,如表單中填入的賬號密碼;若請求方法是PUT或POST寫操作,也不能緩存,一般緩存的都是GET操作的數據(就算是GET操作若包含用戶的認證授權類信息也不能緩存)
?
可在cache server上自定義緩存策略(把某些資源根據我們自己的理解從原始server上剝離出來自己定義這些資源的緩存時間),如cache server到原始server上請求數據,若請求的是站點的LOGO圖片,雖原始server告訴cache server可緩存10min,但cache server(管理者)覺得該內容是靜態的而且很長時間都不會變,于是cache server響應時告訴client可緩存半年,client在自己本地私有緩存中保存的內容越多,那向server發起請求的或獲取的數據就越少,資源發送少了,帶寬占用率就小了,client從本地緩存直接拿數據會很快,這樣用戶體驗度就好
?
?cache server放到離client越近越好(最好放在家門口),盡量將資源丟到用戶的緩存中,我們電腦上或手機上使用時間長了會緩存一些數據,這樣使得上網速度更快并節省流量,某些軟件會提示清理垃圾,若清理了下次請求將占用帶寬重新獲取
?
緩存擴展結構:CDN(cache delivery network,內容分發網絡),如圖:
client到server這之間可定義N層緩存(n個cache server,cache server之間是分層次的),client請求到cache server1,1號發現自己沒有要響應的內容時它不會去找原始server,它會先找它的兄弟服務器(cache server2)2若沒有再去找它的父cache server3,3沒有找它的父cache server4,父cache server中沒有,由父緩存找原始server(1和2是兄弟服務器(sibling),3是1的父(parent),4是3的父),這些cache server之間通過內容緩存協議且能共享緩存對象共同組成的網絡叫CDN,由此client請求時在中間這個網絡上就可取得所有內容,同時這些cache server可定義一些策略,如定期到原始server上獲取數據無論client有無請求
為使用戶體驗好同時又減輕server壓力使用CDN,如下圖四個區域組成的CDN
未用CDN前,DNS解析:www.magedu.com? in?A? 1.1.1.1
使用CDN,DNS要解析成別名,指向cache server上的某一個,如指向杭州CDN節點(www.magedu.com? in?CNAME? hz.cdn.com),這樣杭州用戶訪問會很快,其它區域的用戶訪問還是很慢,用智能DNS解決(根據client來源判定它屬于哪個區域網絡,于是DNS解析時不是四個都返回,而是僅返回離它最近最快的那個cache server的域名)
智能DNS+CDN這才是真正意義的CDN,當client請求時由該區域的CDN節點響應內容,若該節點沒相應內容,它不去找源站而是找離它近的節點,兄弟服務器和父服務器都沒有才找源站
?
這些cache server能根據內容緩存協議來實現緩存對象共享,高級CDN還能實現內容路由(某個cache server上沒有內容時自動找有內容的cache server),使得盡可能不去找原始server,這并不能完全避免找原始server(如動態內容),就算緩存的內容是靜態的,也不會把整站的內容都緩存上去,只能緩存一部分,若緩存策略定義的好,將站點的熱區數據都拉到cache server上實現盡可能多的在cache server上緩存
CDN通常是按流量收費,視頻站點和圖片站點都要用CDN否則流量大了很容易垮掉
對于中小型電子商務站點可自建CDN,前提要使用智能DNS(可自建智能DNS,也可使用公共的智能DNS server如dnspod)
注: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編碼的數據庫
?
varnish(https://www.varnish-cache.org/):
互聯網早期的cache server是squid(烏賊,章魚,八爪魚)
varnish本身是reverse proxy server同時又提供cache功能,配置簡單、接口簡單、監控接口豐富,由于采用新架構設計,之后擴展要比squid容易,功能與nginx近似,但varnish在創建連接、維持連接的能力比nginx差遠了,通常使用nginx+varnish(nginx處理連接,varnish專門負責緩存),也可nginx+squid(squid功能很強大,支持正向代理、反向代理、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 interface(GUI接口)
?
子進程(child|cache進程,child提供服務、發送至后端并響應用戶請求;cache緩存管理的進程,緩存清理、緩存有效期限檢查等):
command line
storage/hashing(存儲緩存,用key定義查找標準,將key放在某個backet中實現O(1)的查找,查找到的內容即是value)
log/stats(varnish的日志不是保存在file中,有磁盤IO,而是在內存中,啟動服務時就明確說明用多大空間保存日志,空間占完后將覆蓋之前的文件繼續使用,一圈圈輪著使用,日志記錄有client的請求數、client請求命中數、沒命中數、server運行多長時間等;可用工具將日志導出查看,如varnishlog等)
accept(接收用戶請求并將請求轉至workerthreads上)
backend communication(后端主機通信)
worker threads(一個線程響應多個請求,child進程會為每個會話啟動一個worker線程,因此,在高并發的場景中可能會出現數百個worker線程甚至更多)
object expiry(從緩存中清理過期內容)
?
varnish的主進程management只有一個,child進程由多個不同的線程組成,varnish總體連接數在大于5000時性能會下降,一般不會讓工作線程接受太多連接,性能有上限,假設有10個varnish server每個平均接受5000個連接,那10個就能接受5W個了,前端nignx已處理一些請求再將多個請求轉到varnish server上,這種架構已達到億級或十億級PV
?
VCL(varnish configuration language),底層用C開發,完全兼容C語言,提供編程接口,要寫程序提供配置文件,用VCL開發程序時指明varnish怎么工作(哪些內容緩存、哪些內容不緩存、哪些內容不通過緩存來取等),為使VCL開發出的程序更加高效,要將其編譯為二進制格式(使用VCL編寫好配置文件后,使用gcc編譯)
配置文件編譯完后生成共享模塊,child/cache如何工作就取決于共享模塊中的定義,二進制格式的配置文件被子進程child/cache讀取,child從后端server取得內容后要緩存在本地,由storage/hashing子模塊將緩存內容存下來
?
VCL工作在varnish的狀態引擎state engine上,在varnish內部有多個state engine(同iptables的netfilter框架中的幾個接口類似(勾子函數),若某個報文不經過這幾個勾子函數將檢測不到,所以這幾個勾子要放在報文必經的路口,使得報文必須要經過這其中1個或幾個勾子,在這些勾子上就能實現管理)
如圖:橢圓表示state engine(又叫domain),菱形表示檢查機制(條件判斷)
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 engine(domain)過來的報文統一處理(vcl_recv、vcl_hit、vcl_miss),統一到一個反向操作上(例如命中后不去找緩存而是找vcl_fetch繼而找后端server))
vcl_fetch(到這個domain上就要聯系后端server,這個域上會定義一些語句來判定哪些內容緩存哪些不緩存(如auth或cookie有關的字串就不緩存))
路線:
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)注釋://和/*(單選注釋);*/(多行注釋)
(2)sub $name(定義函數,subroutine子例程)
(3)不支持循環,有內置變量(內置變量應用位置獨特,有的變量應用在前半段(請求報文首部),有的變量應用在后半段(響應報文首部))
(4)使用終止語句,沒有返回值
(5)域專用(每個state engine定義自己的程序)
(6)操作符(=賦值、==等值比較、~模式匹配、!、&&、||)
VCL的函數不接受參數且沒有返回值,因此并非真正意義的函數,這也限定了VCL內部的數據傳遞只能隱藏在http首部內部進行,VCL的return語句用于將控制權從VCL狀態引擎返回給varnish,而非默認函數,這就是VCL只有終止語句沒有返回值的原因;同時對于每個域來說,可定義一個或多個終止語句,告訴varnish下一步采取何種操作(如查詢緩存或不查詢緩存等)
?
VCL的內置函數:
regsub(str,regex,sub)
regsuball(str,regex,sub)
以上兩項實現替換(substituend,用于將regexp匹配到的str替換為sub,相當于nginx的rewrite,而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等)
?
?
?
?
?
以上是學習《馬哥運維課程》做的筆記。
轉載于:https://blog.51cto.com/jowin/1739282
總結
以上是生活随笔為你收集整理的Linux运维 第三阶段 (十八) varnish的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 中this、getCon
- 下一篇: iOS 设计模式之工厂模式