Varnish(二)Varnish4.0安裝與配置

十五十六發表於2018-09-19

安裝

系統:CentOS7
Varnish版本:4.0
後端web伺服器:192.168.253.158
Varnish代理伺服器:192.168.253.128

192.168.253.128主機上

#wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo  #安裝epel源,如果已經有了就不需要執行這個命令 (這條命令對應的是CentOS7系統)
yum install varnish -y  

Varnish是一個快取伺服器,也是個代理伺服器。如果沒有後端真實伺服器存在提供服務,它快取什麼?所以需要先設定個後端web伺服器。然後讓Varnish去代理後端伺服器。

192.168.253.158上設定後端web伺服器

systemctl  stop firewalld 
setenforce  0
yum install nginx -y 
nginx 
echo "192.168.253.158"> /usr/share/nginx/html/index.html 

在這裡插入圖片描述

在這裡插入圖片描述

192.168.253.128上修改配置檔案

[root@localhost etc]# grep -vE "#|^$" /etc/varnish/default.vcl 
vcl 4.0;
backend default {
    .host = "192.168.253.158"; ## 代理後端的WEB伺服器
    .port = "80";
}
sub vcl_recv {
}
sub vcl_backend_response {
}
sub vcl_deliver {
}

啟動Varnish

systemctl start varnish

進入Varnish的命令列介面

varnishadm  -S /etc/varnish/secret   # /etc/varnish/secret是認證檔案

在這裡插入圖片描述

可以看到子程式正在執行

配置檔案目錄結構

[root@localhost etc]# tree   /etc/varnish/
/etc/varnish/
├── default.vcl  ##預設的Varnish配置檔案
├── secret        ##認證檔案
└── varnish.params ##Varnish執行引數配置

varnish.params配置檔案

這個檔案設定執行varnish時的引數

# Varnish environment configuration description. This was derived from
# the old style sysconfig/defaults settings

# Set this to 1 to make systemd reload try to switch VCL without restart.
RELOAD_VCL=1

# Main configuration file. You probably want to change it.
VARNISH_VCL_CONF=/etc/varnish/default.vcl  #預設的vcl配置檔案

# Default address and port to bind to. Blank address means all IPv4
# and IPv6 interfaces, otherwise specify a host name, an IPv4 dotted
# quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=192.168.1.5
VARNISH_LISTEN_PORT=6081   #varnish監聽的埠

# Admin interface listen address and port  varnish管理介面監聽的地址
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1  
VARNISH_ADMIN_LISTEN_PORT=6082  

# Shared secret file for admin interface #認證檔案路徑
VARNISH_SECRET_FILE=/etc/varnish/secret

# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details. #指定快取 存放的位置
VARNISH_STORAGE="malloc,256M"
# malloc[,size]  記憶體儲存,[,size]用於定義空間大小;重啟後所有快取項失效;
# file[,path[,size[,granularity]]]  磁碟檔案儲存,黑盒;重啟後所有快取項失效;
# persistent,path,size   檔案儲存,黑盒;重啟後所有快取項有效;實驗;

# User and group for the varnishd worker processes  所屬的屬主和屬組
VARNISH_USER=varnish 
VARNISH_GROUP=varnish

# Other options, see the man page varnishd(1)  #一些額外引數的選項
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"

VCL

簡介

Varnish Configuration Language (VCL)是一種特定於域的語言,用於描述Varnish Cache的請求處理和文件快取策略。載入新配置時,由Manager程式建立的VCC程式將VCL程式碼轉換為C.此C程式碼通常由gcc共享物件編譯。然後將共享物件載入到child程式中。

vcl狀態引擎

在VCL狀態引擎中,狀態之間具有相關性,但彼此間互相隔離,每個引擎使用return(x)來退出當前狀態並指示varnish進入下一個狀態。
varnish開始處理一個請求時,首先需要分析HTTP請求本身,比如從首部獲取請求方法、驗正其是否為一個合法的HTT請求等。當這些基本分析結束後就需要做出第一個決策,即varnish是否從快取中查詢請求的資源。這個決定的實現則需要由VCL來完成,簡單來說,要由vcl_recv方法來完成。如果管理員沒有自定義vcl_recv函式,varnish將會執行預設的vcl_recv函式。然而,即便管理員自定義了vcl_recv,但如果沒有為自定義的vcl_recv函式指定其終止操作(terminating),其仍將執行預設的vcl_recv函式。事實上,varnish官方強烈建議讓varnish執行預設的vcl_recv以便處理自定義vcl_recv函式中的可能出現的漏洞。

常用的有幾個狀態引擎

vcl_recv

vcl_recv是在Varnish完成對請求報文的解碼為基本資料結構後第一個要執行的子例程,它通常有四個主要用途:
(1)修改客戶端資料以減少快取物件差異性;比如刪除URL中的www.等字元;
(2)基於客戶端資料選用快取策略;比如僅快取特定的URL請求、不快取POST請求等;
(3)為某web應用程式執行URL重寫規則;
(4)挑選合適的後端Web伺服器;

vcl_backend_response

vcl_backend_response在讀取了後端伺服器響應報文後執行

vcl_deliver

vcl_deliver,向客戶端傳送響應之前執行

vcl_init

在處理任何請求之前要執行的vcl程式碼:主要用於初始化VMODs;

vcl_fini

所有的請求都已經結束,在vcl配置被丟棄時呼叫;主要用於清理VMODs;

基本語法規則

  • VCL 檔案以 vcl 4.0 ; 開頭
  • //, # 和 /* foo */ 表示註釋
  • 函式用sub關鍵字宣告,例如 sub vcl { … } ;
  • 不支援迴圈,有內建變數
  • 需要用return () 進行下一個動作。例子:return(action)
  • 域專用
  • include “foo.vcl”; 包含一個VCL檔案
  • import foo; 載入Varnish模組(VMOD)

VCL內建函式,關鍵字和操作符

函式

  • regsub(str, regex, sub) :用於基於正規表示式搜尋指定的字串並將其替換(替換一次)為指定的字串
  • regsuball(str, regex, sub) :用於基於正規表示式搜尋指定的字串並將其替換(全部替換)為指定的字串
  • ban(boolean expression)
  • hash_data(input):對input進行hash
  • synthetic(str)

關鍵詞

  • call subroutine
  • return(action)
  • new
  • set
  • unset

操作符:

  • ==, !=, ~, >, >=, <, <=
  • 邏輯操作符:&&, ||, !
  • 變數賦值:=

VCL內建的公用變數

公用變數名稱 含義
req.backend 指定對應後端主機
server.ip 表示伺服器IP
client.ip 表示客戶端IP
req.request 指定請求的型別,例如GET、HEAD和POST等
req.url 指定請求的地址
req.proto 表示客戶端發起請求的HTTP協議版本
req.http.header 表示對應請求中的HTTP頭部資訊
req.restarts 表示請求重啟的次數,預設最大值為4

Varnish 在向後端主機請求時,可以使用的公用變數

公用變數名稱 含義
beresp.request 指定請求的型別,例如GET或HEAD等
beresp.url 指定請求的地址
beresp.proto 表示客戶端發起請求中的HTTP協議版本
beresp.http.header 表示對應請求中的HTTP頭部資訊
beresp.ttl 表示快取的生存週期,也就是cache保留多長時間單位是秒

從cache或後端主機獲取內容後,可以使用的公用變數

公用變數名稱 含義
obj.status 表示返回內容的請求狀態碼,例如200、302、504等
obj.cacheable 表示返回的內容是否可以快取,也就是說,如果HTTP返回的是200、203、300、301、302、404或410等,並且有非0的生存期,則可以快取
obj.valid 表示是否是有效的HTTP應答
obj.response 表示返回內容的請求狀態資訊
obj.proto 表示返回內容的HTTP協議版本
obj.ttl 表示返回內容的生存週期,也就是快取時間,單位是秒
obj.lastuse 表示返回上一次請求到現在的間隔時間,單位是秒

對客戶端應答時,可以使用的公用變數

公用變數名稱 含義
resp.status 表示返回客戶端的HTTP狀態程式碼
resp.proto 表示返回客戶端的HTTP協議版本
resp.http.header 表示返回客戶端的HTTP頭部資訊
resp.response 表示返回客戶端的HTTP狀態資訊

例子

舉例1 :如果請求命中快取了,則在響應報文首部X-Cache新增HIT via + 服務端ip,如果沒有命中則新增MISS via + 服務端ip。因為我們新增的報文是在varnish返回客戶端這個過程。所以最好在vcl_deliver這個函式裡面新增。obj.hits是內建變數,用於儲存某快取項的從快取中命中的次數;

[root@localhost etc]#  grep -Ev "#|^$" /etc/varnish/default.vcl
vcl 4.0;
backend default {
    .host = "192.168.253.158";
    .port = "80";
}
sub vcl_recv {
}
sub vcl_backend_response {
}
sub vcl_deliver {
		set resp.http.X-Cache = "HIT via " + server.ip;
    } 
    else {
		set resp.http.X-Cache = "MISS via " + server.ip;
    }
}

動態修改配置檔案

varnishadm  -S /etc/varnish/secret #進入Varnish的命令列管理
#varnish的命令列管理介面內
vcl.load  X-cache /etc/varnish/default.vcl #裝載 /etc/varnish/default.vcl配置檔案,命名為X-cache
vcl.use X-cache #使用X-cache這個配置檔案

在這裡插入圖片描述
可以看到X-cache這個配置檔案已經啟用了

可以訪問一次192.168.253.128的6081埠
在這裡插入圖片描述
這時候我們看到快取沒有命中。因為是第一次訪問,我們再次重新整理就可以看到命中了
在這裡插入圖片描述

舉例2:強制對某類資源的請求不檢查快取

vcl_recv {
		if (req.url ~ "(?i)^/(login|admin)") {  #(?i)不區分大小寫
				return(pass);
		}
}

舉例3:對於特定型別的資源,例如公開的圖片等,取消其私有標識,並強行設定其可以由varnish快取的時長; 定義在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;
	}
}

舉例4:定義在vcl_recv中;

if (req.restarts == 0) {
    if (req.http.X-Fowarded-For) {
		set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;
	} else {
		set req.http.X-Forwarded-For = client.ip;
	}
}		

修建快取物件

清理快取有2種方法purge和ban

purge

purge用於清理快取中的某特定物件,因此,在有著明確要修剪的快取物件時可以使用此種方式。

vcl示例

vcl 4.0;
backend default {
    .host = "192.168.253.158";
    .port = "80";
}

acl purgers {  ##設定訪問控制列表
    "127.0.0.0"/8;
    "192.168.253.0"/24;
       
}

sub vcl_purge {
	return (synth(200,"Purged")); #合成一個200響應碼顯示已經刪除了。
}

sub vcl_recv {
    if (req.method == "PURGE") {
        if (!client.ip ~ purgers) {   ##如果客戶端不再訪問控制列表裡面 則返回405錯誤
  	    return(synth(405,"Purging not allowed for " + client.ip));
	}
	return(purge);
    }
}
sub vcl_backend_response {
}
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;
    }
}

重新裝載配置檔案

[root@localhost ~]# varnishadm  -S /etc/varnish/secret  
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-693.el7.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-4.0.5 revision 07eff4c29

Type 'help' for command list.
Type 'quit' to close CLI session.

vcl.load PURGE_ACL /etc/varnish/default.vcl ##裝載配置檔案 
200        
VCL compiled.
vcl.use PURGE_ACL   ## 使用配置檔案
200        
VCL 'PURGE_ACL' now active

可以看到一開始是命中快取的,當使用PURGE請求的時候就吧快取刪除了,於是下一次訪問時候,顯示MISS。說明通過PURGE方法我們刪除了快取物件
在這裡插入圖片描述

ban

ban()是一種從已快取物件中過濾(filter)出某此特定的物件並將其移除的快取內容重新整理機制,不過,它並不阻止新的內容進入快取或響應於請求。在Varnish中,ban的實現是指將一個ban新增至ban列表(ban-list)中,這可以通過命令列介面或VCL實現,它們的使用語法是相同的。ban本身就是一個或多個VCL風格的語句,它會在Varnish從快取雜湊(cache hash)中查詢某快取物件時對搜尋的物件進行比較測試。

定義好的所有ban語句會生成一個ban列表(ban-list),新新增的ban語句會被放置在列表的首部。快取中的所有物件在響應給客戶端之前都會被ban列表檢查至少一次,檢查完成後將會為每個快取建立一個指向與其匹配的ban語句的指標。Varnish在從快取中獲取物件時,總是會檢查此快取物件的指標是否指向了ban列表的首部。如果沒有指向ban列表的首部,其將對使用所有的新新增的ban語句對此快取物件進行測試,如果沒有任何ban語句能夠匹配,則更新ban列表。

對ban這種實現方式持反對意見有有之,持贊成意見者亦有之。反對意見主要有兩種,一是ban不會釋放記憶體,快取物件僅在有客戶端訪問時被測試一次;二是如果快取物件曾經被訪問到,但卻很少被再次訪問時ban列表將會變得非常大。贊成的意見則主要集中在ban可以讓Varnish在恆定的時間內完成向ban列表新增ban的操作,例如在有著數百萬個快取物件的場景中,新增一個ban也只需要在恆定的時間內即可完成。

使用方法有2種
(1)在命令列介面使用
格式:

ban <field> <operator> <arg>

示例
在這裡插入圖片描述
現在快取是命中的。

[root@localhost varnish]# varnishadm  -S /etc/varnish/secret 
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-693.el7.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-4.0.5 revision 07eff4c29

Type 'help' for command list.
Type 'quit' to close CLI session.

ban req.url  ~ /.*html   ##ban掉匹配到/.*html的url
200        

然後我們再次訪問
在這裡插入圖片描述

(2)在配置檔案中定義,使用ban()函式;

[root@localhost ~]# grep -Ev "#|^$"  /etc/varnish/default.vcl
vcl 4.0;
backend default {
    .host = "192.168.253.158";
    .port = "80";
}
acl purgers {
    "127.0.0.0"/8;
       
}
sub vcl_recv {
    if (req.method == "BAN") {
  	    return(synth(405,"Purging not allowed for " + client.ip));
	}
        else{
            ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
	    return(synth(200,"Ban added"));
        }
    }
}
sub vcl_backend_response {
}
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;
    }
}

測試之前我們訪問了一次顯示快取命中了,然後使用BAN請求。顯示BAN 新增成功
在這裡插入圖片描述

然後我們再訪問一次,顯示快取沒有命中“MISS”
在這裡插入圖片描述

我們這個配置檔案的訪問控制列表僅允許127.0.0.1執行ban操作。當我們使用192.168.253.128這個ip訪問時,會顯示不允許執行此操作
在這裡插入圖片描述

相關文章