1. 程式人生 > >緩存服務器之memcached和varnish

緩存服務器之memcached和varnish

錯誤 並發連接數 系統 接口 rac cli 內存碎片 集群 ini

兩類緩存服務器:
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代表公共緩存)

2.條件式請求:
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