緩存服務器之memcached和varnish
1.代理式緩存服務器;proxy-like cache server;
2.旁掛式緩存服務器;bypass cache server;
緩存服務器也可以根據緩存數據內容分類:
1.數據緩存;data cache
2.頁面緩存;page cache
數據存在訪問熱區,指被經常訪問的數據。
緩存的實質是:用空間換時間;
緩存的局部性特征:空間局部性和時間局部性:
緩存的時效性:
過期清理:PURGE,修剪;
未過期但溢出清理:LRU(最少使用原則);
未過期但被修改:PURGE,修剪;
緩存命中率:Hits/(Hits + Miss) ,取值範圍區間是(0,1),通常也會用百分數進行表示;
頁面命中率:基於命中的頁面數量進行統計衡量的一種標準;
數據緩存與否:
1.私有數據:private data,放置於私有緩存中;
http/1.1版本後的首部中,提供了一個Cach-Control的首部;Cache-Control首部的值中包含有private字樣,或者提供了Cookie或者Cookie2的首部;此類數據大多數都是由瀏覽器完成緩存;
2.公共數據:public data,可以放置於公共緩存,也可以放置於私有緩存中;
此類數據大多數緩存在反代服務器上或者專用的Cache Server上;
小部分也可以緩存在瀏覽器上;
註意:
瀏覽器的緩存(一般是私有緩存):
僅針對於單獨的用戶生效,使用戶重復訪問某資源時能夠加速訪問;
為前端調度器或反代服務器加速資源訪問,降低後端資源服務器的訪問壓力;
對於緩存服務器來說,緩存的處理步驟(大致成功的處理步驟):
接收請求 --> 解析請求(從請求報文的http協議首部中提取URL及其他相關的首部信息) --> 查詢緩存 --> 緩存數據的新鮮度檢測 --> 構建響應報文 --> 發送響應報文--> 記錄日誌
緩存數據的有效性判斷機制:
1.過期時間:
HTTP/1.0:
Expires,絕對時間;
HTTP/1.1:
1.Expires
2.Cache-Control(首部):max-age=86400
3.Cache-Control:s-maxage=10000 (s代表公共緩存)
Last-Modified/If-Modified-Since :響應報文/請求報文的條件請求
Etag/If-None-Match :擴展標簽,對標簽進行哈希計算;If-None-Match:如果不匹配,返回200代表不匹配
示例:查看百度的logo資源:
Cache-Control max-age=2592000 //緩存資源的最大有效時間
ETag "593645fd-664" //得到的16進制的哈希值
Expires Wed, 11 Jul 2018 03:43:28 GMT //過期時間
Last-Modified Tue, 06 Jun 2017 06:04:45 GMT //自 06 Jun 2017 06:04:45 GMT這個時間點開始資源無變化(GMT:格林尼治時間)
一、memcached緩存服務器:
屬於旁掛式緩存服務器,也屬於數據緩存;
memcached存儲形式:
1.將所有數據采用鍵值對兒的形式存儲於內存當中;
2.無持久存儲功能;
3.通常用於緩存小文件,小數據,單項緩存數據內容上限是1MB;
memcached由LiveJournal公司旗下的子公司Danga Interactive研發者Brad Fitzpatrick研發;
memcached特性:
1.k/v cache;可序列化數據,扁平化數據; //常見的還有JSON,也是序列化數據
2.存儲項:key(鍵), value(值), flag(16位二進制數字,0-65535), expire_time(超時時間), length(保存數據的長度)等簡單部分組成;
3.旁掛式緩存,功能實現一半依賴於客戶端,另一半靠memcached server;
4.O(1)的查找和執行效率;
5.可以構建分布式緩存系統,各服務器之間互不通信的分布式集群系統;
6.緩存數據的處理方式(較為特殊):
1)緩存空間耗盡:根據LRU(最近最少使用算法)完成清理過期數據;
2)緩存項過期:惰性清理機制---用來盡可能減少內存碎片
7.內存分配方式:
slab allocation:按照頁面進行打散,將打散的頁面分成若幹個更小的頁面,最大1M
facter:增長因子;默認1.25倍遞增;小頁面根據增長因子來分配空間大小,最後會留下一個最大不超過1M的空間。
安裝配置memcached:
1.base源中有對應的rpm包;可以直接使用yum方式安裝內容;
~]# yum install memcached -y
2.從memcached.org官方站點下載源代碼包,編譯安裝;
memcached緩存服務監聽的端口:
11211/TCP, 11211/UDP;
memcached緩存服務程序安裝後的默認環境:
主程序:/usr/bin/memcached
環境配置文件:/etc/sysconfig/memcached
~]# cat /etc/sysconfig/memcached
PORT="11211" //監聽的端口號
USER="memcached" //程序屬於哪個用戶
MAXCONN="1024" //服務的最大連接數
CACHESIZE="64" //緩存大小默認為64
OPTIONS="" //其他選項默認為空
memcached緩存服務使用的協議是memcached協議,memcached協議支持的數據傳輸格式是:
1.文件格式
2.二進制格式
交互式操作(~]# telnet+載有memcached服務主機的IP地址+端口號(默認是11211),使用telnet命令進入交互式操作模式):
命令:
1.統計類:stats, stats items(緩存項查看), stats slabs(內存空間的查看), stats sizes
2.管理類:set(修改特定鍵的值), add(添加一個新的鍵), replace(替換原有鍵的值), append(在原有鍵值後附加一個值), prepend(在原有鍵值前附加一個值), delete(刪除鍵), incr(給鍵添加值), decr(給鍵刪除值), flush_all(清空所有鍵)
3.查看類:get
memcached交互式命令的一般格式:
<command> key_name [flags] [expire_time] [length_bytes] \n
key_name:鍵名
[flags]:標誌位,範圍是0-65535
[expire_time]:鍵最大緩存時間(秒)
[length_bytes]:字符長度
例:
添加一個新鍵:
add testkey 0 300 11
hello world
STORED
查看新鍵:
get testkey
VALUE testkey 0 11
hello world
END
在新鍵後添加字符並查看:
添加:
append testkey 0 300 2
hi
STORED
查看:
get testkey
VALUE testkey 0 13
hello worldhi
END
在新鍵前添加字符並查看:
添加:
prepend testkey 0 300 3
hi
STORED
查看:
get testkey
VALUE testkey 0 14
hi hello world
END
memcached命令選項:
-c num :指名並發連接數量,默認是1024
-m num :分配多大的內存空間,默認是64M
-u username :指定哪個用戶啟動memcached服務進程
-p port :指定端口號,默認是11211
-U port :指定UDP協議的端口號,默認是11211,0是關閉
-l ipaddress :監聽哪一個地址,默認是所有
-f facter :指明增長因子,默認是1.25倍
-t thread_num :設置線程數,默認是4個線程
-v,-vv,-vvv :顯示的詳細信息程度
二、VARNISH緩存服務器:
varnish緩存服務器是屬於頁面緩存服務器的一種,用來為客戶端請求提供查詢結果,也屬於代理式緩存服務器。
varnish緩存服務器特點:
varnish緩存服務器可以實現的功能:反向代理 + 緩存服務器
varnish緩存服務器默認在內存中占用128M內存空間去進行緩存服務
緩存服務器的實現:
開源解決方案:
squid:上世紀90年代中期出現;使用率較低
varnish:反向代理式緩存:使用率較高的緩存服務器實現方案;
https://www.varnish-software.com/ //商業版本服務站點
http://varnish-cache.org/ //開源站點
varnish程序的組織結構:
1.Management進程:
1)varnish的主進程;
2)提供命令行工具的訪問接口,用來管理子進程,初始化緩存;
2.Child/Cache進程:擁有多種線程模型,如下:
command line
storage/hashing
log/stats
accept
worker threads
object expiry
backend communication
...
3.VCL compiler:C compiler(gcc)
varnish的線程池作用:
統計數據:數據統計和計數器;
日誌區域:日誌數據;
VCL文件的處理方式:
vcl compiler (vcl編譯器編譯完成)--> C compiler (再到C的編譯器中編譯處理)--> shared object
vcl配置文件的重載工具:
/usr/sbin/varnish_reload_vcl
VCL:Varnish Configuration Language,varnish配置語言;
統一存放於後綴名為".vcl"的文件中,在初次安裝了varnish之後,在配置主目錄中會自動創建出一個名為"default.vcl"的文件,但其內容幾乎為空;
varnish的安裝:
在EPEL源中直接提供了varnish的穩定版本;
安裝命令:yum install -y varnish (需先配置EPEL源)
varnish的程序環境:
1.配置文件:
/etc/varnish/default.vcl
定義緩存策略的默認配置文件,主要用於配置各Child/Cache線程的工作屬性;
/etc/varnish/varnish.params
定義varnish緩存服務的運行時參數以及工作特性;
/etc/varnish/secret
在使用varnishadm命令行管理工具時,為了安全起見使用的預共享密鑰;
2.主程序: /usr/sbin/varnishd
1)CLI(簡單的命令行接口管理工具):
/usr/bin/varnishadm
2)Share Memory Log交互工具:
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop
開啟varnish日誌記錄(默認沒有開啟):
1./usr/bin/varnishlog
2./usr/bin/varnishncsa(建議在需要開啟日誌記錄的時候開啟,因為其更接近於Apache的command的命令形式)
3)緩存測試工具:
/usr/bin/varnishtest
4)varnish的Unit FIle:
/usr/lib/systemd/system/varnish.service:管理varnish的Management進程;
實現日誌持久化存儲的服務文件;
/usr/lib/systemd/system/varnishlog.service
/usr/lib/systemd/system/varnishncsa.service
主程序:/usr/sbin/varnishd
varnishd - HTTP accelerator daemon --http加速器守護進程
常用選項:
-a address[:port][,address[:port][...]
指定用於接收客戶端請求所監聽的地址和服務端口,默認值為127.0.0.1:6081
-b host[:port]:添加一個backend sever的主機和端口號
-T address[:port]:實現管理的時候需要用到的地址和端口號;
-f config:
指明此次需要編譯並裝載的VCL配置文件,默認為/etc/varnish/default.vcl;
-p param=value
設置varnish線程模型的運行時參數和參數值;
大多數的運行時參數都有默認值,不要輕易嘗試調整運行時參數的值;
在命令行工具中使用此選項調整的運行時參數的值,僅當次生效;
-r param[,param...]
將運行時參數設置為只讀屬性;意味著當再次運行時,其值無法被修改;
-s [name=]type[,options]:指定緩存的存儲機制
定義緩存數據的存儲方式,目前有三種存儲機制:
1.malloc[,size]:性能最好,但是所有的數據保存在內存中;
2.file[,path[,size[,granularity]]]:只是一種黑盒文件,內容無法觀察;鍵值對兒存放於內存當中,哈希值存放於磁盤中,保證快速檢索,不會占用內存太多空間
3.persistent,path,size (experimental,體驗測試版):持久存儲(機制不成熟)
-T address[:port]
在指定的IP地址和端口號上提供管理接口;默認為127.0.0.1:6082;
-u user、-g group
指定允許varnish服務進程的系統用戶和系統組,默認均為varnish;
運行時參數的配置文件:/etc/varnish/varnish.params
DAEMON_OPTS="-p param1=value1 -p param2=value2 ..."
thread_pool_min=5
thread_pool_max=500
thread_pool_timeout=300
命令行管理工具:varnishadm (交互式模式)
varnishadm - Control a running Varnish instance
常用選項:
-S secret_file
指定通過命令行工具實現驗證時的預共享密鑰文件;
-T address:port
指定管理地址和端口;
交互式模式的命令:
help [<command>] :varnishadm命令幫助
ping [<timestamp>] :做連通測試
auth <response> :做認證
quit :退出交互式模式
banner :做條幅
status :狀態輸出
start :啟動varnish服務(不建議使用) //重啟、關閉、開啟都會把緩存清空,這是致命的
stop :關閉varnish服務(不建議使用)
管理vcl:
vcl.load <configname> <filename>:裝載並且編譯vcl文件
vcl.inline <configname> <quoted_VCLstring>:
vcl.use <configname>:激活已經編譯好的vcl文件;
vcl.discard <configname>:刪除已經編譯好的非激活狀態下的vcl配置文件;
vcl.list:vcl配置文件一共有哪些;
param.show [-l] [<param>]:列舉所有運行時參數並且輸出詳細參數;
param.set <param> <value>:臨時修改某個運行時參數的值,一次性修改,重啟後恢復默認
panic.show:顯示運行時參數列表或顯示指定的運行時參數的詳細信息;
panic.clear:清空運行時參數列表;
storage.list:顯示緩存存儲相關信息;
vcl.show [-v] <configname> :顯示default.vcl所有配置歷史更改列表,包括正在使用和使用過的;
backend.list [<backend_expression>] :後端服務器列表顯示;
backend.set_health <backend_expression> <state> :設置後端服務器將康狀態碼;
常用的命令:
VCL配置文件管理相關:
vcl.load:裝載並編譯VCL配置文件;
vcl.use:激活已經編譯完成的VCL配置文件;
vcl.discard:刪除非激活狀態下的VCL配置文件;
運行時參數相關:
param.show:顯示運行時參數列表或顯示指定的運行時參數的詳細信息;
param.set:實時設置或修改運行時參數的值;(不要輕易嘗試修改,一定要清楚操作的目的)
緩存存儲相關:
storage.list:顯示緩存存儲相關信息;
後端服務器相關:
backend.list:顯示可以直接訪問的後端服務器列表;
backend.set_health:指明後端服務器的健康狀態檢測方式;
VCL:Varnish Configuration Language;
"域"專有類型的配置語言;
VCL中定義了多個狀態引擎,各狀態引擎之間存在相關性,同時又彼此隔離;每個狀態引擎內都可以使用return()關鍵字指明各狀態引擎之間的關聯關系;在VCL文件中,狀態引擎使用如下的方式進行定義:
sub STATE_ENGINE_NAME { ...; }
sub+狀態引擎的名字+{ 配置指令1;配置指令2;... }
三個varnish狀態引擎版本對比以及數據處理流程:
1.varnish 2.0-狀態引擎包括:
vcl_recv:接收請求,並且判斷是否可以使用緩存數據;
vcl_hash:對於從backend端取回的數據,如果可被緩存,則進行哈希計算;
vcl_hit:對於請求的資源可以在緩存對象中直接獲取;
vcl_miss:對於請求的資源無法在緩存對象中直接獲取;
vcl_deliver:構建響應報文;
vcl_fetch:從backend端取回數據;
varnish2.0的處理流程:
1.vcl_recv --> vcl_hash --> vcl_hit --> vcl_deliver
2.vcl_recv --> vcl_hash --> vcl_miss --> vcl_fetch --> vcl_deliver
3.vcl_recv --> vcl_fetch --> vcl_deliver (不走緩存)
2.varnish 3.0狀態引擎包括:
vcl_recv:接收請求,並且判斷是否可以使用緩存數據;
vcl_hash:對於從backend端取回的數據,如果可被緩存,則進行哈希計算;
vcl_hit:對於請求的資源可以在緩存對象中直接獲取;
vcl_miss:對於請求的資源無法在緩存對象中直接獲取;
vcl_deliver:構建響應報文;
vcl_fetch:從backend端取回數據;
較varnish2.0新增:
vcl_pass:對於本來可以從緩存中查找到資源明確的設置不使用緩存;多數用於私有緩存的查找策略;
vcl_pipe:對於無法理解的請求,直接按照原樣的封裝直接代理至backend端;
vcl_error:本地發生錯誤時,構建錯誤響應報文;
varnish的處理流程:
1.vcl_recv --> vcl_hash --> vcl_hit --> vcl_deliver
2.vcl_recv --> vcl_hash --> vcl_hit --> vcl_pass --> vcl_fetch -->vcl_deliver
3.vcl_recv --> vcl_hash --> vcl_miss --> vcl_fetch --> vcl_deliver
4.vcl_recv --> vcl_hash --> vcl_miss --> vcl_pass --> vcl_fetch --> vcl_deliver
5.vcl_recv --> vcl_pass --> vcl_fetch --> vcl_deliver
6.vcl_recv --> vcl_pipe
3.varnish 4.0+狀態引擎包括:
vcl_recv:接收請求,並且判斷是否可以使用緩存數據;
vcl_hash:對於從backend端取回的數據,如果可被緩存,則進行哈希計算;
vcl_hit:對於請求的資源可以在緩存對象中直接獲取;
vcl_miss:對於請求的資源無法在緩存對象中直接獲取;
vcl_deliver:構建響應報文;
vcl_pass:對於本來可以從緩存中查找到資源明確的設置不使用緩存;多數用於私有緩存的查找策略;
vcl_pipe:對於無法理解的請求,直接按照原樣的封裝直接代理至backend端;
較於varnish3.0新增:
vcl_backend_fetch:從backend端取回數據;
vcl_backend_response:處理從backend取回的數據;
vcl_backend_error:本地發生錯誤時,構建錯誤響應報文;
vcl_synth:主要用於緩存修剪及信息發送;(由varnish3.0中的error變化而來)
vcl_purge:修剪緩存;
varnish的處理流程:
1.vcl_recv --> vcl_hash --> vcl_hit --> vcl_deliver
2.vcl_recv --> vcl_hash --> vcl_hit --> vcl_pass --> vcl_backend_fetch --> vcl_backend_response --> vcl_deliver
3.vcl_recv --> vcl_hash --> vcl_pass --> vcl_backend_fetch --> vcl_backend_response --> vcl_deliver
4.vcl_recv --> vcl_hash --> vcl_miss[ --> vcl_pass ] --> vcl_backend_fetch --> vcl_backend_response --> vcl_deliver
5.vcl_recv --> vcl_hash --> vcl_purge --> vcl_synth
6.vcl_recv --> vcl_hash --> vcl_pipe
7.vcl_recv --> vcl_hash --> waiting
↑ ↓
←←←←←
varnish中還有兩個特殊的狀態引擎:
vcl_init:
在處理任何請求之前要調用此引擎,主要用於初始化VMODs;
vcl_fini:
在所有的請求都已經處理結束,在VCL的配置被丟棄時調用此引擎,主要用於清理VMODs;
VCL的語法格式:
1.與C、C++語言的語法非常相似,可以支持C、C++或perl風格的註釋方式:
//, #, / ... /
2.VCL不支持循環和跳轉語句;但可以是if條件分支(單分支、雙分支及多分支);
if的單分支格式:
if (condition) {
...;
}
if的雙分支格式:
if (condition) {
...;
} else {
...;
}
if的多分支格式:
if (condition1) {
...;
} elseif (condition2) {
...;
} else {
...;
}
3.所有的字符串內容應該放置於""之內,且不能使用換行符;
4.支持內建和自定義的ACL;
5.支持豐富的操作符:=(賦值符號), ==(等值比較), >, >=, <, <=, !, &&(與運算), ||(或運算), ~
6.使用return()關鍵字來決定下一個處理流程使用哪個引擎,且return()關鍵字無返回值;
7.支持內建變量及自定義變量,並且內建變量之間存在依賴關系,只能在特定的引擎中調用特定的內建變量;
set var_name = value
unset var_name
VCL中的內建變量:
req.:request,表示客戶端發送來的請求報文相關的變量;
bereq.:backend request,由varnish向backend端主機發送請求的相關變量;
resp.:response,由varnish響應給前端設備或客戶端的響應報文的相關變量;
beresp.:backend response,由backend主機響應給varnish的響應報文的相關變量;
obj.*:存在在緩存空間中的緩存對象相關的變量,只讀;
常用的內建變量:
req類:
req.http.HTTP_HEADER_NAME:
req.http.Cache-Control
req.http.User-Agent
req.http.Host:
...
req.url:客戶端發送來的請求報文中的URL相關信息;
if (req.url ~ (?i)\.php$) {
return(pass);
}
req.method:客戶端發送來的請求報文中的請求資源的方法;
req.proto:客戶端發送來的請求報文中使用的http協議版本;
bereq類:
bereq.http.HTTP_HEADER_NAME:
bereq.http.Cache-Control
bereq.http.User-Agent
bereq.http.Host:
bereq.url:varnish向backend端發送的請求報文中的URL相關信息;
bereq.method:varnish向backend端發送的請求報文中的請求資源的方法;
bereq.proto:varnish向backend端發送的請求報文中使用的http協議版本;
bereq.backend:指明要調度的後端主機;
resp類:
resp.http.HTTP_HEADER_NAME:
resp.status:varnish自身向客戶端發送的響應報文中的響應狀態碼;
resp.proto:varnish自身向客戶端發送的響應報文中的http協議版本號;
beresp類:
beresp.http.HTTP_HEADER_NAME:
beresp.status:backend端主機向varnish發送的響應報文中的響應狀態碼;
beresp.proto:backend端主機向varnish發送的響應報文中的http協議版本號;
beresp.backend.name:backend端主機型varnish發送的響應報文中的主機名;
beresp.ttl:backend端主機響應的內容剩余的可緩存時長;
obj類:
obj.hits:指定的對象從緩存中命中的次數;(實時數值)
obj.miss:指定的對象從緩存中未命中的次數;(實時數值)
obj.ttl:指定的對象在緩存中剩余有效緩存時長;
VCL的自定義變量:
定義變量:
set VAR_NAME = VALUE;
取消定義的變量:
unset VAR_NAME;
為了方便展示下面的配置示例,說一下環境:
1.在安裝好的varnish緩存服務器主機上,/etc/varnish/varnish.params中修改監聽的後端服務器端口號為80而不是默認的6081,其他默認就可以,方便顯示;
2.在/etc/varnish/varnish.params中VARNISH_LISTEN_PORT=80,然後保存退出重啟服務(重啟命令:systemctl reload varnish.service)
3.iptables -F關閉防火墻;
4.setenforce 0 更改SELinux的狀態,防止訪問受影響;
緩存服務器之memcached和varnish