6.1 Varnish緩存

分佈式緩存


  • 緩存概念

緩存是分佈式系統中的重要組件,主要解決高併發,大數據場景下,熱點數據訪問的性能問題。提供高性能的數據快速訪問。

WebCache web 緩存,是一種緩存技術,用於臨時存儲(緩存)的網頁文件,如 HTML 頁面和圖像等靜態資源(此處不絕對,也可以緩存動態頁面,但是存儲到本地後也爲靜態文件),減少帶寬以及後端服務器的壓力,通常一個 WebCache 也是一個反向代理軟件,既可以通過緩存響應用戶的請求,當本地沒有緩存時,可以代理用戶請求至後端主機。

緩存的原理

  1. 將數據寫入/讀取速度更快的存儲(設備)
  2. 將數據緩存到離應用最近的位置
  3. 將數據緩存到離用戶最近的位置

緩存的類型

CDN緩存
CDN主要解決將數據緩存到離用戶最近的位置,一般緩存靜態資源文件(頁面,腳本,圖片,視頻,文件等)。國內網絡異常複雜,跨運營商的網絡訪問會很慢。爲了解決跨運營商或各地用戶訪問問題,可以在重要的城市,部署CDN應用。使用戶就近獲取所需內容,降低網絡擁塞,提高用戶訪問響應速度和命中率。

反向代理緩存
反向代理是指在網站服務器機房部署代理服務器,實現負載均衡,數據緩存,安全控制等功能。

分佈式Cache
分佈式緩存,主要指緩存用戶經常訪問數據的緩存,數據源爲數據庫。一般起到熱點數據訪問和減輕數據庫壓力的作用。

本地應用緩存
本地緩存是指應用內部的緩存,標準的分佈式系統,一般有多級緩存構成。本地緩存是離應用最近的緩存,一般可以將數據緩存到硬盤或內存。

  • 代理緩存

與 Redis 或者 Memcached 不同,代理緩存通常運行在代理服務器上,而前者則旁掛在後端服務器外側,爲後端服務器提供數據緩存。

緩存有效性驗證機制

    如果原始內容未發生改變,則僅響應首部(不附帶body部分),響應碼304(Not Modified)
    如果原始內容發生改變,則正常響應,響應碼200
    如果原始內容消失,則響應404,此時緩存中的cache object應被刪除

代理緩存HTTP報文

Cache-Control:針對上述的“Expires時間是相對服務器而言,無法保證和客戶端時間統一”的問題,http1.1新增了 Cache-Control 來定義緩存過期時間。注意:若報文中同時出現了 Expires 和 Cache-Control,則以 Cache-Control 爲準。

    語法:<span class="hljs-string">"Cache-Control" <span class="hljs-string">":" cache-directive</span></span>

當該字段值爲no-cache的時候,會知會客戶端不要對該資源讀緩存,即每次都得向服務器發一次請求才行。Cache-Control也是一個通用首部字段,這意味着它能分別在請求報文和響應報文中使用。
也就是說優先級從高到低分別是 Pragma -> Cache-Control -> Expires 。

Pragma:設置頁面是否緩存,爲Pragma則緩存,no-cache則不緩存

If-None-Match:當資源過期時(使用Cache-Control標識的max-age),發現資源具有Etage聲明,則再次向web服務器請求時帶上頭If-None-Match(Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。

If-Modified-Since:當資源過期時(使用Cache-Control標識的max-age),發現資源具有Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭 If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。

Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的唯一標識(生成規則由服務器覺得)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後得到的。

Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。

Expires:有了Pragma來禁用緩存,自然也需要有個東西來啓用緩存和定義緩存時間,對 http1.0 而言,Expires 就是做這件事的首部字段。 Expires的值對應一個 GMT(格林尼治時間),如果還沒過該時間點則不發請求。

Varnish


  • Varnish構架

Management

Management進程主要實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行接口等。 Management進程會每隔幾秒鐘探測一下Child進程以判斷其是否正常運行,如果在指定的時長內未得到Child進程的回 應,Management將會重啓此Child進程
varnishadm 命令行接口,目前 vagent 2 爲收費接口,而 telnet 是純文本傳輸,所以只能使用varnishadm.Varnish 服務運行時監聽在兩個套接字上,一個監聽前端發送來的請求(tcp:6081),另一個監聽管理接口的管理命令(tcp:6082)

Child/Cache Process

Acceptor:接收新的連接請求
Worker:用於處理並響應用戶請求
Expiry:從緩存中清理過期cache object

Shared Memory Log

shared memory log,共享內容日誌方式存儲,一般其大小爲90MB,分爲兩部分:前一部分爲計數器、後一部分爲客戶請求相關的數據
可以使用 varnishlog 將日誌文件從內存提取到磁盤當中保存

VCL(Varnish Configuration Language)

VCL 是 varnish 配置緩存策略的工具,它是一種基於“域”(domain specific)的簡單編程語言,它支持有限的算術運算和邏輯運算操作、允許使用正則表達式進行字符串匹配、允許用戶使用set自定義變量、支持if判 斷語句,也有內置的函數和變量等。使用VCL編寫的緩存策略通常保存至.vcl文件中,其需要編譯成二進制的格式後才能由varnish調用。事實上,整 個緩存策略就是由幾個特定的子例程如vcl_recv、vcl_fetch等組成,它們分別在不同的位置(或時間)執行,如果沒有事先爲某個位置自定義子 例程,varnish將會執行默認的定義。

VCL策略在啓用前,會由management進程將其轉換爲C代碼,而後再由gcc編譯器將C代碼編譯成二進制程序。編譯完成後,management負責將其連接至varnish實例,即child進程。正是由於編譯工作在child進程之外完成,它避免了裝載錯誤格式 VCL 的風險。因此,varnish修改配置的開銷非常小,其可以同時保有幾份尚在引用的舊版本配置,也能夠讓新的配置即刻生效。編譯後的舊版本配置通常在 varnish重啓時纔會被丟棄,如果需要手動清理,則可以使用 varnishadm 的 vcl.discard 命令完成。

varnish緩存功能有如下優點

  1. 是基於內存緩存,重啓後數據將消失;
  2. 利用虛擬內存方式,IO性能好。
  3. 支持設置0~60秒內的精確緩存時間。
  4. VCL配置管理比較靈活
  5. 32位機器上緩存文件大小最大爲2G
  6. 具有強大的管理功能,例如top、stat、admin、list等。
  7. 狀態機設計巧妙,結構清晰
  8. 利用二叉堆管理緩存文件,達到積極刪除目的
  • Varnish工作原理

上圖是 Varnish 官方站點提供的 varnish 工作流程圖。大致總結一下可以理解爲以下四種常見情況

還有兩種引擎圖中沒有 vcl_init 與 vcl_finish 分別負責
    在處理任何請求之前要執行的vcl代碼:主要用於初始化VMODs
    所有的請求都已經結束,在vcl配置被丟棄時調用;主要用於清理VMODs

  • varnish命令

varnishd

程序選項:
    -a address[:port][,address[:port][...],默認爲6081端口; 
    -T address[:port],默認爲6082端口;
    -s [name=]type[,options],定義緩存存儲機制;
    -u user
    -g group
    -f config:VCL配置文件;
    -F:運行於前臺

varnishadm

    語法:varnishadm -S 祕鑰文件 -T IP地址:端口 [-t 超時時長] [-n 緩存名稱]

配置文件相關:
    vcl.list  列出vcl配置列表
    vcl.load  裝載,加載並編譯
    vcl.use  激活
    vcl.discard  刪除
    vcl.show [-v] <configname>  查看指定的配置文件的詳細信息

運行時參數:
    param.show -l:顯示列表;
    param.show <PARAM>
    param.set <PARAM> <VALUE>

緩存存儲:
    storage.list

後端服務器:
    backend.list 

Varnish運行時參數

在線程池內部,其每一個請求由一個線程來處理; 其worker線程的最大數決定了varnish的併發響應能力

thread_pools:線程數,最好小於或等於CPU核心數量; 
thread_pool_max: 每線程池的最大線程數;
thread_pool_min:額外意義爲“最大空閒線程數”;

設置方式:

    vcl.param 
    param.set

永久有效的方法:

保存在 varnish.params 中
    語法:DEAMON_OPTS="-p PARAM1=VALUE -p PARAM2=VALUE"

  • Varnish日誌

varnishstat

varnishstat 工具用於顯示 Varnish 緩存的狀態信息

選項:

    -1  一次顯示所有狀態信息
    -f  查看指定字段名稱列表

[root@CentOS74 ~]# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
MAIN.cache_hit              52         0.01 Cache hits
MAIN.cache_miss             75         0.01 Cache misses

varnishtop

varnishtop 工具用於顯示 Varnish 的緩存使用排名

選項:

    -1   一次顯示所有狀態信息
    -i taglist  可以同時使用多個-i選項,也可以一個選項跟上多個標籤;
    -I <[taglist:]regex>  對指定的標籤的值基於regex進行過濾; 
    -x taglist  排除列表
    -X  <[taglist:]regex>  對指定的標籤的值基於regex進行過濾,符合條件的予以排除;

varnishlog

varnishlog 工具用於顯示 Varnish 的日誌信息

varnishncsa

varnishncsa 工具用於顯示 combined 格式的 Varnish 的日誌信息

  • 日誌的持久化

varnishlog 和 varnishncsa 都能夠以守護進程的方式運行在後臺

[root@CentOS74 ~]# cat /usr/lib/systemd/system/varnishncsa.service /usr/lib/systemd/system/varnishlog.service
[Unit]
Description=Varnish Cache HTTP accelerator NCSA logging daemon
After=varnish.service

[Service]
RuntimeDirectory=varnishncsa
Type=forking
PIDFile=/run/varnishncsa/varnishncsa.pid
User=varnish
Group=varnish
ExecStart=/usr/bin/varnishncsa -a -w /var/log/varnish/varnishncsa.log -D -P /run/varnishncsa/varnishncsa.pid  #可以修改日誌保存的路徑
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target
[Unit]
Description=Varnish Cache HTTP accelerator logging daemon
After=varnish.service

[Service]
RuntimeDirectory=varnishlog
Type=forking
PIDFile=/run/varnishlog/varnishlog.pid
User=varnish
Group=varnish
ExecStart=/usr/bin/varnishlog -a -w /var/log/varnish/varnish.log -D -P /run/varnishlog/varnishlog.pid   #可以定義日誌保存的路徑
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章