1. 程式人生 > >Linux自學筆記——varnish

Linux自學筆記——varnish

varnish cache proxy lB

Web Cache

緩存:緩存就是數據交換的緩沖區(cache),當某一硬件要讀取數據時,會首先從緩存中查找需要的數據,如果找到了則直接執行,找不到的話則從內存中找。由於緩存的運行速度比內存快很多,故緩存的作用就是幫助硬件更快的運行。

程序具有局部性:時間局部性,空間局部性。

緩存存儲方式:key-value

Key:訪問路徑,url,hash

Value:web content

熱點數據:局部性的數據;

命中率:hit/(hit+miss)

文檔命中率:從文檔個數進行衡量;

字節命中率:從內容大小進行衡量

註意:

緩存對象:生命周期;定期清理;

緩存空間耗盡:LRU(最近最少使用)

可緩存,不可緩存(用戶私有數據)

緩存處理的步驟:

接收請求 à 解析請求(提取請求的URL及各種首部)à 查詢緩存 à 新鮮度檢測 à 創建響應報文 à 發送響應 à 記錄日誌

新鮮度檢測機制:

過期日期:

HTTP/1.0 Expires

Expires

:Thu,04 Jun 2015 23:38:18 GMT

HTTP/1.1 Cache-Control:max-age

Cache-Control:max-age=600

有效性再驗證:revalidate

如果原始內容未改變,則僅響應首部(不附帶body部分),響應碼304(Not modified)

如果原始內容發生改變,則正常響應 , 響應碼為200;

如果原始內容消失,則響應404,此時緩存中的cache object也應該被刪除;

條件式請求首部:

If-Modified-Since:基於請求內容的時間戳驗證;

If-Unmodified-Since

If-Match

If-None-Match

Etag: faiy89345

常用的開源解決方案:squid ,varnish,本文重點介紹varnish;

Varnish

程序架構圖:

技術分享圖片

管理進程:編譯vcl並應用新配置;監控varnish;初始化varnish;CLI接口

Child/cache

Acceptor:接收新的連接請求;

worker threads:處理用戶請求;

Expiry:清理緩存中的過期對象;

日誌:Shared Memory Log,共享內存日誌大小默認一般為90MB,分為兩部分,前一部分為計數器,後一部分請求相關數據;

vcl:Varnish Configuration Language

保存策略配置接口;

基於“域”的簡單編程語言;

內存分配和回收:

malloc(),free()

varnish如何存儲緩存對象?可以通過以下三種方式;

file:單個文件;不支持持久機制;

malloc:內存

persistent:基於文件的持久存儲;

varnish的主要配置文件及工具:

技術分享圖片

配置varnish的三種應用:

1. Varnish應用程序的命令行參數;

監聽的socket,使用的存儲類型等等;額外的配置參數;

-p parm=value

-r param,param,…:設定只讀參數列表;

/etc/varnish/varnish.params

技術分享圖片

2. –p選項指明的參數:

運行時參數:

也可在程序運行中,通過其CLI進行配置;

3. vcl:配置緩存系統的緩存機制;

通過vcl配置文件進行配置;

先編譯,後應用;

依賴於c編譯器;

Note

1) varnish是一個web代理緩存服務器,既然是代理就要代表原始web服務器工作,所以,接收的用戶請求會首先發送到varnish,那這樣一來按理說就應該監聽在80端口;其實不然,為了防止和本機的80端口起沖突,varnish默認是監聽在6081端口的;這是因為雖然varnish為代理緩存服務器,但並不會讓其直接面向用戶,而是通過前端的nignx或者haproxy將用戶的請求反代至varnish,由varnish完成緩存管理,如果本地緩存沒有,varnish再去查找原始服務器,如果有就直接返回給前端反代服務器。

2) 6082端口為基於命令行工具去管理和控制varnish的接口,為了安全起見監聽在本機的127.0.0.1的地址;

演示:使用varnish代理緩存後端web服務

實驗環境:兩臺服務器,一臺作varnish代理緩存服務器,一臺作後端服務器;

Ip地址分配:

varnish緩存服務器:192.168.19.203

後端RS:192.168.19.143

1. 配置文件/etc/varnish/varnish.params如下,(一般默認不改變)

技術分享圖片

2. 編輯/etc/varnish/default.val文件,反向代理至後端服務器;

技術分享圖片

3. 啟動varnish服務並查看端口;

技術分享圖片

4. 訪問網站測試;

技術分享圖片

Note:後面需要加端口6081,

命令行工具:

varnishadm命令以及vcl配置文件的重載:

重載vcl配置文件:

varnish_reload_vcl

varnishadm命令:

varnishadm -S /etc/varnish/secret -T IP:PORT

技術分享圖片

vcl

請求流程圖:

技術分享圖片

state engine:各引擎之間存在一定程度上的相關性;前一個engine如果可以有多種下遊engine,則說明engine需要用return指明要轉移的下遊engine;

vcl_recv

vcl_hash

vcl_hit

vcl_miss

vcl_fetch

vcl_deliver

vcl_pipe

vcl_pass

vcl_error

編程語言語法:

1) //,#,/* */用於註釋;會被編譯器忽略;

2) sub $name:用於定義子例程;

sub vcl_recv {

}

3) 不支持循環;

4) 有眾多內置的變量,變量可調用位置與state engine有密切相關性;

5) 支持終止語句,return(action):沒有返回值;

6) 域專用 ;

7) 操作符:=,==,~,!,&&,||

條件判斷語句:

if (CONDTION) {

} else {

}

變量賦值:set name=value

unset name

req.http.HEADER:調用request報文中http報文中http協議的指定的HEADER首部

req.http.X-Forwarded-For

req.http.Auhtorization

req.http.cookie

req.request:請求方法

client.ip:客戶端IP;

state engine workflow(v3):

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_deliver

vcl_recv --> vcl_pipe

state engine(v4)

vcl_recv

vcl_pass

vcl_pipe

vcl_hash

vcl_hit

vcl_miss

vcl_backend_fetch

vcl_backend_response

vcl_backend_error

vcl_purge

vcl_synth

https://www.varnish-software.com/book/4.0/chapters/VCL_Basics.html

sub vcl_recv {

if (req.method == "PRI") {

/* We do not support SPDY or HTTP/2.0 */

return (synth(405));

}

if (req.method != "GET" &&

req.method != "HEAD" &&

req.method != "PUT" &&

req.method != "POST" &&

req.method != "TRACE" &&

req.method != "OPTIONS" &&

req.method != "DELETE") {

/* Non-RFC2616 or CONNECT which is weird. */

return (pipe);

}

if (req.method != "GET" && req.method != "HEAD") {

/* We only deal with GET and HEAD by default */

return (pass);

}

if (req.http.Authorization || req.http.Cookie) {

/* Not cacheable by default */

return (pass);

}

return (hash);

}

定義在vcl_deliver中,向響應給客戶端的報文添加一個自定義首部X-Cache

if (obj.hits>0) {

set resp.http.X-Cache = "HIT";

} else {

set resp.http.X-Cahce = "MISS";

}

演示:通過判斷想應報文緩存命中的次數來判斷是否命中緩存;

1) 編輯配置文件/etc/varnish/default.vcl;

技術分享圖片

2) 重載配置文件,過程如下;

技術分享圖片

3) 瀏覽器測試;

技術分享圖片

Varnish中的內置變量:

變量種類:

client

erver

req

resp

bereq

beresp

obj

storage

bereq

bereq.http.HEADERS: 由varnish發往backend server的請求報文的指定首部;

bereq.request:請求方法;

bereq.url

bereq.proto:協議的版本

bereq.backend:指明要調用的後端主機;

beresp

beresp.proto:後端服務器響應的協議版本

beresp.status:後端服務器的響應的狀態碼

beresp.reason:原因短語;

beresp.backend.ip:後端響應的ip

beresp.backend.name:BE主機的主機名

beresp.http.HEADER: 從backend server響應的報文的首部;

beresp.ttl:後端服務器響應的內容的余下的生存時長;

obj

obj.ttl: 對象的ttl值;

obj.hits:此對象從緩存中命中的次數;

server

server.ip

server.hostname

req

resp

演示1:強制對某類資源的請求不檢查緩存,之類以login和admin為例;

1) 提供測試頁面環境;

技術分享圖片

2) 訪問測試;

技術分享圖片

可以看出,第一次沒有命中,但是以後都能命中的。

3) 現在我們修改配置文件,在vcl_recv下添加以下內容,強行對此資源不檢查緩存;

技術分享圖片

4) 重新裝載配置文件,測試(裝載配置文件過程,這裏不再多說)

技術分享圖片

可以看出,這兩次訪問,都沒有擊中緩存;

演示2:設定多個後端主機,並分別以負載均衡和動靜分離的方式調度;

動靜分離方式調度:

1) 提供RS2的php頁面測試環境;(註意,要安裝httpd+php)

技術分享圖片

2) 編輯配置文件,添加內容如下;

技術分享圖片

3) 重載配置文件,並測試;

訪問.php文件時:

技術分享圖片

Note:php右上角的圖片沒有顯示出來,是因為靜態資源發往了192.168.19.144這臺主機,而這臺主機上又沒有這張圖片。所以顯示不出來;

訪問html文件時:

技術分享圖片

負載均衡調度:使用前需要導入:import director

1) 編輯配置文件,首先導入import director模塊,內容如下;

技術分享圖片

2) 重載配置文件,測試;

技術分享圖片

Note:varnish的負載均衡調度是對請求的不同資源的負載均衡調度,請求統一資源,它只會調度至一開始調度的服務器;

定義健康狀態監測;

backend server的定義:

backend name {

.attribute = "value";

}

.host: BE主機的IP;

.port:BE主機監聽的PORT;

.probe: 對BE做健康狀態檢測;

.max_connections:並連接最大數量;

後端主機的健康狀態檢測方式:

probe name {

.attribute = "value";

}

.url: 判定BE健康與否要請求的url;

.expected_response:期望響應狀態碼;默認為200;

.request:發出的具體請求

.window:基於最近的多少次檢查來判斷其健康狀態;

.threshhold:最近.window中定義的這麽多次檢查中至有.threshhold定義的次數時成功的;

.interval:監測額度;

.timeout:超時時長;

演示3:設定varnish對後端主機做健康狀態監測;

1) 使用varnishadm命令可以查看後端主機是否做了檢測狀態監測;

技術分享圖片

2) 編輯配置文件/etc/varnish/default.vcl,定義健康狀態監測的probe;

方法一:

技術分享圖片

方法二:

技術分享圖片

3) 重載配置文件,查看後端主機是否開啟健康狀態檢測;

技術分享圖片

4) 瀏覽器訪問測試看是否能正常訪問;

技術分享圖片

補充:

移除單個緩存對象

purge用於清理緩存中的某特定對象及其變種(variants),因此,在有著明確要修剪的緩存對象時可以使用此種方式。HTTP協議的PURGE方法可以實現purge功能,不過,其僅能用於vcl_hit和vcl_miss中,它會釋放內存工作並移除指定緩存對象的所有Vary:-變種,並等待下一個針對此內容的客戶端請求到達時刷新此內容。另外,其一般要與return(restart)一起使用。

下面是個在VCL中配置的示例。

acl purgers {

"127.0.0.1";

"192.168.0.0"/24;

}

sub vcl_recv {

if (req.request == "PURGE") {

if (!client.ip ~ purgers) {

error 405 "Method not allowed";

}

return (lookup);

}

}

sub vcl_hit {

if (req.request == "PURGE") {

purge;

error 200 "Purged";

}

}

sub vcl_miss {

if (req.request == "PURGE") {

purge;

error 404 "Not in cache";

}

}

sub vcl_pass {

if (req.request == "PURGE") {

error 502 "PURGE on a passed object";

}

}

客戶端在發起HTTP請求時,只需要為所請求的URL使用PURGE方法即可,其命令使用方式如下:

# curl -I -X PURGE http://varniship/path/to/someurl

補充資料:

varnish的線程模型:

cache-worker線程

cache-main線程:此線程只有一個,用於啟動caceh;

ban luker

acceptor

epoll:線程池管理器

expire:清理過期緩存

varnish定義其最大並發連接數:線程池模型:

thread_pools:線程池個數;默認為2;

thread_pool_max:單線程池內允許啟動的最多線程個數;

thread_pool_min

thread_pool_timeout:多於thread_pool_min的線程空閑此參數指定的時長後即被purge;

varnish的param查看及改變:

param.show [-l] [param]

param.set [param] [value]

varnish的命令行工具:

varnishadm,

varnishtop: 內存日誌區域查看工具

RxHeader User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36

其中:

RxHeader:稱為tag, 基於tag過濾,可使用-i或-x選項;

User-Agent起始的內容:稱為日誌信息,可使用-I或-X選項進行過濾;

-I regexp: 僅顯示被模式匹配到的條目

-X regexp:僅顯示不被模式匹配到的條目

-C: 忽略字符大小寫;

-d: 顯示已有日誌;

varnishstat

-f field, field, ...

-l: 列出所有可用字段

-x: xml輸出格式

-j: json輸出格式

varnishlog, varnishncsa




Linux自學筆記——varnish