一. Web Page Cache 相關概念
1. 程序的運行具有局部性原理:
#緩存可以提供http的速度,也是基于這兩個原理
時間局部性: 即一個資源被訪問到后,短時間內有可能被再次訪問到,
同時資源也遵循28定律,有20%的資源為高頻訪問資源.
空間局部性: 即空間中相近的資源將更快被訪問到
2. cache命中率:
緩存命中率:hit/(hit+miss)
頁面命中率:基于頁面數量進行衡量
字節命中率:基于頁面的體積進行衡量
緩存存在熱區,即局部性;
時效性:
緩存空間耗盡:LRU
過期:緩存清理
3. 資源緩存與否:(分類)
私有數據:private,private cache;
此類數據僅提供私人緩存即瀏覽器緩存
公共數據:public, public or private cache;
此類數據可以作為公共緩存或私人緩存
4. Cache-related Headers Fields #緩存相關的http首部
The most important caching header fields are:
Expires:絕對過期時間;
Expires:Thu, 22 Oct 2026 06:34:30 GMT
Cache-Control : 緩存控制,即定義是否緩存
Etag: 版本標簽,用于彌補時間戳無法精確定義資源是否改變
Last-Modified: 最后修改時間(服務端發往客戶端,存在于響應報文)
If-Modified-Since: 最后修改時間(客戶端發往服務端, 存在于請求報文)
If-None-Match:匹配Etag, 若匹配即未修改,返回304狀態嗎
Vary:告訴下游代理是使用緩存響應還是從原始服務器請求
Age:從原始服務器到代理緩存形成的估算時間(以秒計,非負)
5.緩存有效性判斷機制:
過期時間:Expires
HTTP/1.0
Expires 絕對過期時間
HTTP/1.1
Cache-Control: maxage= 相對過期時間
Cache-Control: s-maxage= 公共資源相對過期時間
條件式請求:
Last-Modified/If-Modified-Since
Etag/If-None-Match
示例:
Expires:Thu, 13 Aug 2026 02:05:12 GMT
Cache-Control:max-age=315360000
ETag:"1ec5-502264e2ae4c0"
Last-Modified:Wed, 03 Sep 2014 10:00:27 GMT
6. 請求報文中的cache-control對應值:
cache-request-directive =
"no-cache"
#緩存下來后,但響應時要求每次都需要向原始服務器做校驗
"no-store" :
#不緩存
"max-age" "=" delta-seconds
# 相對最大有效時長,即只接受age值小于此值的未過期對象
"max-stale" [ "=" delta-seconds ]
#接受過期對象,但是過期時間必須小于此值
"min-fresh" "=" delta-seconds
#接受其新鮮生命期大于其當前 Age 跟 min-fresh 值之和的緩存對象
"no-transform"
#未改變
"only-if-cached"
#只有緩存中有相應資源時,客戶端才能收到響應
cache-extension
7. 響應報文中的cache-control對應值:
cache-response-directive =
"public" #公共資源
| "private" [ "=" <"> 1#field-name <"> ]
#指定為私有資源
| "no-cache" [ "=" <"> 1#field-name <"> ]
#略
| "no-store"
#略
| "no-transform"
#略
| "must-revalidate"
#類似 no-cache, 但是強制性更大
| "proxy-revalidate"
#類似must-revalidate,但只作用于代理端
| "max-age" "=" delta-seconds
| "s-maxage" "=" delta-seconds
| cache-extension
======================================================================================
二.varnish
1.開源解決方案:
squid:
varnish:
2. varnish官方站點: http://www.varnish-cache.org/
This is Varnish Cache, a high-performance HTTP accelerator.
版本: Community
Enterprise —帶有web GUI 功能
#目前最新為5.0, 3–4.0使用居多,并且vcl 語法互不兼容
3. 程序架構及組成:
Manager進程: 即父進程
Cacher進程(真正提供響應請求處理的),包含多種類型的線程:
accept, worker, expiry, …
shared memory log:
統計數據:計數器;
日志區域:日志記錄;
varnishlog, varnishncsa, varnishstat…
varnishadm : varnish cli 交互式專用管理工具
配置接口:VCL
Varnish Configuration Language,
vcl complier –> c complier –> shared object
#VCL規則需要由vcl complier 編譯器 調用c 編譯器編譯后,成為一個共享對象
才能供varnish加載使用
————————————————————————–
4. varnish的程序環境:
/etc/varnish/varnish.params: 配置varnish服務進程的工作特性,例如監聽的地址
和端口,緩存機制;
注意:
早期的配置為/etc/sysconfig/varnishd/下的文件
/etc/varnish/default.vcl:配置各Child/Cache線程的工作屬性;
配置文件的工作機制:
以變量形式定義varnish 自身的工作特性,各變
在/etc/varnish/varnish.params中定義;
同時,在啟動時,由/usr/lib/systemd/system/varnish.service
負責調用varnish.params文件
備注:
1. 修改varnish工作個性配置,即/etc/varnish/varnish.params,
不需要重新編譯vcl,與之無關,重啟varnish.server 即可
2. 修改vcl模板配置時,常為修改/etc/varnish/default.vcl
并且,修改完成后,需要用特定命令varnish_reload_vcl
或者varnishadm進行重載
主程序:
/usr/sbin/varnishd
CLI interface:
/usr/bin/varnishadm
Shared Memory Log交互工具:
/usr/bin/varnishhist
#歷史記錄
/usr/bin/varnishlog
#最為詳細的log記錄,基于報文首部來分來
/usr/bin/varnishncsa
#基于httpd combind類似的格式
/usr/bin/varnishstat
#即時各狀態的信息
/usr/bin/varnishtop
#基于請求數量由大到小的順序排序的日志
測試工具程序:
/usr/bin/varnishtest
VCL配置文件重載程序:
/usr/sbin/varnish_reload_vcl
Systemd Unit File:
/usr/lib/systemd/system/varnish.service
#varnish服務:
/usr/lib/systemd/system/varnishlog.service
/usr/lib/systemd/system/varnishncsa.service
#日志持久,滾動的服務;
默認VCL配置文件: /etc/varnish/default.vcl
# 默認此文件為空,可自行添加自定義項目
#默認已經啟用內建vcl配置, 使用varnishadm –vcl.show -v boot可查看
內建VCL配置文件: /usr/share/doc/varnish-##/builtin.vcl
#可將其復制到/etc/varnish下編譯使用
5.varnish的緩存存儲機制( Storage Types):
· malloc[,size]
內存存儲,[,size]用于定義空間大小;重啟后所有緩存項失效;
· file[,path[,size[,granularity]]]
文件存儲,黑盒;重啟后所有緩存項失效;
#對外抽象為單一的一個日志文件,且僅varnish 能識別(黑盒)
· persistent,path,size
文件存儲,黑盒;重啟后所有緩存項有效;實驗;
6. varnish程序的選項:
#用于手動以命令形式修改varnish 的工作參數,效果與手動修改配置文件一樣
(程序選項:/etc/varnish/varnish.params文件)
-a address[:port][,address[:port][…],默認為6081端口;
#緩存服務監聽接口
#使用時,需要改為80端口;
-T address[:port],默認為6082端口;
#管理監聽接口
-s [name=]type[,options],定義緩存存儲機制;
默認為file:
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"
可修給為malloc,內存工作機制:
VARNISH_STORAGE="malloc,512M"
-u user #默認運行用戶為varnish
-g group #默認組為varnish
-f config:VCL配置文件;
-F:運行于前臺;
…
運行時參數:/etc/varnish/varnish.params文件, DEAMON_OPTS
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p
thread_pool_timeout=300"
-p param=value:設定運行參數及其值; 可重復使用多次;
-r param[,param…]: 設定指定的參數為只讀狀態,即不允許運行時修改
重載vcl配置文件:
~ ]# varnish_reload_vcl
============================================================
三. varnishadm
1. 常用選項:
-S /etc/varnish/secret -T [ADDRESS:]PORT
#使用varnishadm 時候,需要使用與服務器啟動時所用的同一個密鑰文件進行認
證,即/etc/varnish/secret,并-T 指定服務器以及端口,默認為8082端口
#當執行任何命令時,若執行成功,則會返回200代碼
help [<command>] #獲取命令幫助
ping [<timestamp>] #檢測服務器工作狀態,正常則返回pang
auth <response> #
quit
banner #重新加載varnishadm標題
status #獲取狀態信息
start #varnishd服務啟動
stop #服務停止
vcl.load <configname> <filename> #VCL模板命令
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
vcl.show [-v] <configname>
param.show [-l] [<param>] ?。_\行參數相關命令
param.set <param> <value>
panic.show
panic.clear
storage.list #緩存存儲情況
backend.list [<backend_expression>] #后端服務器列表
backend.set_health <backend_expression> <state> #后端服務器健康情況
ban <field> <operator> <arg> [&& <field> <oper> <arg>]…
#用于定義如何手動清理緩存
ban.list
2.配置文件相關:
vcl.list #列出已經成功編譯的vcl版本
available : 可以使用版本
active: 正在啟用的版本
vcl.load:裝載,加載并編譯;
eg:
vcl.reload testconf1 /etc/varnish/default.vcl
#加載/etc/varnish/default.vcl,并編譯后取名為testconf1
vcl.use:激活;#使用指定版本,注意需要先load才能使用
eg:
vcl.use testconf1
vcl.discard:刪除未被使用的acl版本,即available狀態的
vcl.show [-v] <configname>:查看指定的配置文件的詳細信息;
#用于查看已經生效的配置
eg:
vcl.show -v boot
#此配置信息為默認配置
3. 運行時參數:
param.show -l:顯示列表;其中包含可以修改的全部參數
param.show <PARAM> #顯示指定項的參數
eg:
param.show thread_pool_max
param.set <PARAM> <VALUE>
eg:
param.set thread_pool.max 1024
4. 緩存存儲:
storage.list
5. 后端服務器:
backend.list
===========================================================
四. VCL:
1. vcl :”域“專有類型的配置語言;與varnish內部的 state enging狀態引擎相關;
2. 狀態引擎
VCL狀態引擎切換機制: 內部有多個狀態引擎,狀態之間存在相關性,但彼此間互相隔離;每
個狀態引擎可使用
return(x)指明關聯至哪個下一級引擎;
eg: vcl_hash –> return(hit) –> vcl_hit
兩個特殊的引擎:
vcl_init:在處理任何請求之前要執行的vcl代碼:主要用于初始化VMODs;
vcl_fini:所有的請求都已經結束,在vcl配置被丟棄時調用;主要用于清理VMODs;
3. 請求處理流程:
#詳細處理流程,可以參照/usr/share/doc/varnish-###/builtin.vcl中的定義
(1) state engine /組件 說明:
客戶端請求接收: vcl_recv
url哈希: vcl_hash
緩存命中: vcl_hit
緩存未命中: vcl_miss
報文后端傳送: vcl_pass
后端主機報文獲取: vcl_fetch
緩存項修剪: vcl_purge
session(cookie)/authorization 認證報文后端傳送: vcl_pipe
客戶端響應:vcl_deliver
繁忙等待隊列: vcl_waiting
后端返回報文接收: vcl_backend_response
后端服務器錯誤: vcl_backend_error
后端返回報文可緩存性判斷: cacheable
purge響應報文構建: vcl_synth
(2) 接收請求:vcl_recv;判斷其是否可緩存;
(a) 可緩存:vcl_hash
(i) 命中:vcl_hit
(ii)未命中:vcl_miss –> vcl_fetch
(b) 不可緩存:直接–>vcl_fetch
(c) http方法不可識別: –> vcl_pipe(管道輸送給后端服務器)
(d) purge方法: 修剪緩存對應項–>vcl_synth ()
(e) 服務器繁忙期間 : –> vcl_waiting 請求進入等待隊列
(f) 請求報文首部含有用戶session/authorization–> vcl_pass–>vcl_fetch
傳輸給后端服務器
(g) 非get/head 方法—> vcl_pass, 傳送給后端服務器
(3) #varnish 4.0 內部處理流程圖,
注意: 4.0以前的處理流程會有所不同,部分請求,不會都通往vcl_hash
部分處理路徑:
(1) vcl_hash -(hit)-> vcl_hit –> vcl_deliver
(2) vcl_hash -(miss)-> vcl_miss –> vcl_backend_fetch –> vcl_backend_response –>
vcl_deliver
(3) vcl_hash -(purge)-> vcl_purge –> vcl_synth
(4) vcl_hash -(pipe)-> vcl_pipe
===========================================================
五. VCL語法詳解
1.vcl的語法格式:
(1) VCL files start with vcl 4.0;
#varnish 4.0 acl配置文件必須以"vcl 4.0"
(2) //, # and /* foo */ for comments;
#單行注釋,以及多行注釋, C語言風格;
(3) Subroutines are declared with the sub keyword; 例如sub vcl_recv { …};
#用于定義狀態引擎的工作機制
(4) No loops, state-limited variables(受限于引擎的內建變量);
#不支持循環,但支持條件判斷
(5) Terminating statements with a keyword for next action as argument of the
return() function, i.e.: return(action);
#每個狀態引擎定義sub 最后,使用return 返回值來指定下一個前往的引擎
(6) Domain-specific;
#每個狀態引擎的配置,只對一個狀態引擎有效
2. The VCL Finite State Machine ##狀態引擎工作特性
(1) Each request is processed separately;
#各請求獨立處理
(2) Each request is independent from others at any given time;
#每個請求在任何時候都與其他請求獨立
(3) States are related, but isolated;
#每個狀態都互相獨立
(4) return(action); exits one state and instructs Varnish to proceed to the next
state;
(5) Built-in VCL code is always present and appended below your own VCL;
#內建的cvl
3. 三類主要語法:
1. sub subroutine {
…
}
#用于定義狀態引擎工作配置
eg:
sub vcl_purge {
return (synth(200, "Purged"));
}
—————————————
2. if CONDITION {
…
} else {
…
}
`#用于定義不同報文的處理動作
eg:
if (req.method == "PRI") {
/* We do not support SPDY or HTTP/2.0 */
return (synth(405));
}
——————————————
3. return() # 定義返回值
4. hash_data() #哈希指定url
eg:
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
return (lookup);
}
4.VCL Built-in Functions and Keywords #內建函數
函數:
regsub(str, regex, sub)
#替換str中regex第一次匹配到的內容替換為sub
regsuball(str, regex, sub)
#替換str中regex匹配到的全部內容為替換sub
ban(boolean expression)
#基于布爾型表達式匹配的緩存清理
hash_data(input)
#哈希指定數據
synthetic(str)
Keywords:
call subroutine, #調用子例程
return(action),
new, #
set, #設定變量值
unset #撤銷變量值
操作符:
==, !=, ~, >, >=, <, <=
邏輯操作符:&&, ||, !
變量賦值:=
補充:
(?i) : 為正則表達式開頭項,代表不檢查大小寫
舉例:obj.hits
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;
}
}
內建函數使用限定區域示意圖:
5. 變量類型:
內建變量:
req.*:request,表示由客戶端發來的請求報文相關;
req.http.*
req.http.User-Agent, req.http.Referer, …
bereq.*:由varnish發往BE主機的httpd請求相關;
bereq.http.*
beresp.*:由BE主機響應給varnish的響應報文相關;
beresp.http.*
resp.*:由varnish響應給client相關;
obj.*:存儲在緩存空間中的緩存對象的屬性;只讀;
(obj.hits: 緩存命中計數器)
常用變量:
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
—————————————————————————
示例1:強制對某類資源的請求不檢查緩存:
vcl_recv {
if (req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}
—————————————————————————
示例2:對于特定類型的資源,例如公開的圖片等,取消其私有標識,并強行設定其可以由
varnish緩存的時長;
sbu vcl_backend_response {
if (beresp.http.cache-control !~ "s-maxage") {
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
unset beresp.http.Set-Cookie;
set beresp.ttl = 3600s;
}
}
}
——————————————————————————–
6. 緩存對象的修剪:purge, ban
(1) 能執行purge操作
sub vcl_purge {
return (synth(200,"Purged"));
}
(2) 何時執行purge操作
sub vcl_recv {
if (req.method == "PURGE") {
return(purge);
}
…
}
7. 添加此類請求的訪問控制法則:
acl purgers {
"127.0.0.0"/8;
"10.1.0.0"/16;
}
sub vcl_recv {
if (req.method == "PURGE") {
if (!client.ip ~ purgers) {
return(synth(405,"Purging not allowed for " + client.ip));
}
return(purge);
}
…
}
———————————————————————————–
8. 如何設定使用多個后端主機:
backend default {
.host = "172.16.100.6";
.port = "80";
}
backend appsrv {
.host = "172.16.100.7";
.port = "80";
}
sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint = appsrv;
} else {
set req.backend_hint = default;
}
…
}
9. Director:后端服務器調度器
注意: 使用前需要導入:
import directors;
調度算法: 1.robin
2. random
示例:
import directors; # load the directors
backend server1 {
.host =
.port =
}
backend server2 {
.host =
.port =
}
sub vcl_init {
new GROUP_NAME = directors.round_robin();
GROUP_NAME.add_backend(server1);
GROUP_NAME.add_backend(server2);
}
sub vcl_recv {
# send all traffic to the bar director:
set req.backend_hint = GROUP_NAME.backend();
}
10. BE Health Check:
backend BE_NAME {
.host =
.port =
.probe = {
.url=
.timeout=
.interval=
.window=
.threshhold=
}
}
.probe:定義健康狀態檢測方法;
.url:檢測時請求的URL,默認為”/";
.request:發出的具體請求;
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.magedu.com"
"Connection: close"
.window:基于最近的多少次檢查來判斷其健康狀態;
.threshhold:最近.window中定義的這么次檢查中至有.threshhold定義的次數
是成功的;
.interval:檢測頻度;
.timeout:超時時長;
.expected_response:期望的響應碼,默認為200;
健康狀態檢測的配置方式:
(1) 調用.probe 方式
probe PB_NAME = { }
#先定義probe檢測方式
backend NAME = {
.probe = PB_NAME;
#調用剛定義的檢測方式
…
}
#通過調用.probe方式來檢測指定后端主機健康狀態,可避免代碼冗余
(2) 直接在對應后端主機配置中插入probe 配置
backend NAME {
.probe = {
…#直接在此處插入健康狀態檢測配置
}
}
示例:
probe check {
.url = "/.healthcheck.html ";
.window = 5;
.threshold = 4;
.interval = 2s;
.timeout = 1s;
}
backend default {
.host = "10.1.0.68";
.port = "80";
.probe = check;
}
backend appsrv {
.host = "10.1.0.69";
.port = "80";
.probe = check;
}
=======================================================
六. varnish的運行時參數:
1. 線程模型:
cache-worker
cache-main
ban lurker
acceptor:
epoll/kqueue:
…
2. 線程相關的參數:
在線程池內部,其每一個請求由一個線程來處理; 其worker線程的最大數決定了
varnish的并發響應能力;
thread_pools:Number of worker thread pools. 最好小于或等于CPU核心數量;
thread_pool_max:The maximum number of worker threads in each pool.
thread_pool_min:The minimum number of worker threads in each pool.
額外意義為“最大空閑線程數”;
最大并發連接數=thread_pools * thread_pool_max
thread_pool_timeout:Thread idle threshold. Threads in excess of
thread_pool_min, which have been idle for at least this long, will be
destroyed.
thread_pool_add_delay:Wait at least this long after creating a thread.
thread_pool_destroy_delay:Wait this long after destroying a thread.
設置方式:
vcl.param
永久有效的方法:
varnish.params
DEAMON_OPTS="-p PARAM1=VALUE -p PARAM2=VALUE"
3. varnish日志區域:
shared memory log
計數器
日志信息
1、varnishstat – Varnish Cache statistics
#可顯示當前狀態下的各種信息的實時信息,并會持續刷新
#也是一個各狀態信息的即時統計計數器
-1 :只看某時刻的一個信息,非即時狀態
-1 -f FILED_NAME #顯示指定某字段的瞬時信息
-l:可用于-f選項指定的字段名稱列表;
eg: varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
2、varnishtop – Varnish log entry ranking
#根據數量最大,由高到低的方式排序來顯示各參數
-1 Instead of a continously updated display, print the statistics once
and exit.
-i taglist,可以同時使用多個-i選項,也可以一個選項跟上多個標簽;
-I <[taglist:]regex> #以正則表達式匹配方式顯示匹配項目
-x taglist:排除列表 #不顯示指定的項目
-X <[taglist:]regex>
3、varnishlog – Display Varnish logs
#以羅列各參數的形式顯示日志信息
4、 varnishncsa – Display Varnish logs in Apache / NCSA combined log format
#以類似httpd中combined方式,顯示日志信息
4. 內建函數:
hash_data():指明哈希計算的數據;減少差異,以提升命中率;
regsub(str,regex,sub):把str中被regex第一次匹配到字符串替換為sub;主要用于
URL Rewrite
regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替換為sub;
return():
ban(expression)
ban_url(regex):Bans所有的其URL可以被此處的regex匹配到的緩存對象;
synth(status,"STRING"):purge操作;
總結:
varnish: state engine, vcl
varnish 4.0:
vcl_init
vcl_recv
vcl_hash
vcl_hit
vcl_pass
vcl_miss
vcl_pipe
vcl_waiting
vcl_purge
vcl_deliver
vcl_synth
vcl_fini
vcl_backend_fetch
vcl_backend_response
vcl_backend_error
sub VCL_STATE_ENGINE
backend BE_NAME {}
probe PB_NAME {}
acl ACL_NAME {}
原創文章,作者:ldt195175108,如若轉載,請注明出處:http://www.www58058.com/59971