本節索引
一、緩存基本概念
二、Varnish緩存服務介紹
實驗:實現varinish緩存
三、Varnish狀態引擎
示例:判定curl類型的請求拒絕訪問
示例:判定admin相關的請求拒絕訪問
示例:強制對某類資源請求不檢查緩存
四、Varnish緩存修剪
五、Varnish負載均衡
六、后端服務器健康性狀態檢查
一、緩存基本概念
緩存是指把對某些請求的結果緩存下來,下次請求直接使用數據響應,這樣極大的節省了系統獲取源數據
資源的時間,若我們把大量的請求結果都使用緩存服務器來響應,那么我們可以大大減少計算機數量減少
成本。
數據緩存:從后端關系系數據庫加載到應用服務器進行緩存,存在于數據庫與服務器之間,一般是緩存
SELECT語句。常用有:redis,memcached
頁面緩存:對靜態內容進行緩存,存在于調度器與WEB服務器之間,通常只是緩存GET,HEAD方法的請
求。常用有:squid-cache,varinish-cache
緩存命中:hit,多次查詢能夠在緩存中找到對應項
衡量緩存命中率有兩種標準:
字節命中率
請求命中率
一般來說,當緩存命中率30%以上能夠帶來正向作用
代理式緩存:頁面緩存一般都是代理式緩存,要成為代理式緩存,首先它是臺代理服務器
旁掛式緩存:數據緩存一般都是旁掛式緩存
頁面緩存
squid-cache:歷史悠久頁面緩存系統,類似于Apache與Nginx的關系
varinish-cache:輕量級頁面緩存系統,但穩定性不如squid-cache
基于頁面過期時間的緩存機制(早期):
當客戶端發起請求時,先到緩存服務器中查找有無對應的緩存,如果沒有則將請求發送到后端服務器,后‘’
端服務器發送響應報文并附帶過期時間(expires)
存在問題:
(1)當后端數據發送變化時,緩存變為舊內容
(2)當緩存服務器中數據過期時,有可能還會收到相同的客戶端請求
根據條件式驗證的緩存機制:
存在問題:
粒度大,1秒,可能會出現緩存查詢一致,其實內容已發生變化,得到過期內容
解決方法:
添加一個標簽Etag,將標簽與查詢結果一起返回
http 1.1時代:過期時間+條件式驗證組合使用
緩存預熱:通過自己下載一些網絡請求來訪問緩存服務器以達到最佳狀態
private cache:私有緩存,如瀏覽器緩存
public cache:公共緩存,可能不止一級,如CDN,頁面緩存系統
一般公有緩存+私有緩存應該能到達90%的緩存命中率
CDN:Ccontent Delivery Network內容分發系統
距離判定
鏈路狀態;判定
二、Varnish緩存服務介紹
epel源提供,支持三類緩存:
內存緩存:malloc,重啟后所有緩存項失效;
磁盤緩存:file,黑盒,重啟后所有緩存項失效;
持久緩存:persistent(實驗階段),黑盒,重啟后所有緩存項有效
默認監聽端口:6081,6082(管理端口)
Varinish官方架構圖
varnish主要包含三個部分:
management:提供管理接口,并控制緩存進程的特性
child/cache:提供緩存功能,記錄日志,訪問控制,后端服務器管理
vcl:給child/cache提供配置文件的編譯
Varinishd服務配置:
/etc/varnish/varnish.params: 配置varnish服務進程的工作特性,例如監聽的地址和端口,緩存機制;
/etc/varnish/default.vcl:配置各Child/Cache線程的工作屬性;
主程序:
/usr/sbin/varnishd
CLI interface:
/usr/bin/varnishadm
Shared Memory Log交互工具:
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop?
測試工具程序:
/usr/bin/varnishtest
VCL配置文件重載程序:
/usr/sbin/varnish_reload_vcl
Systemd Unit File:
/usr/lib/systemd/system/varnish.service?? #varnish服務
/usr/lib/systemd/system/varnishlog.service? #logger daemon
/usr/lib/systemd/system/varnishncsa.service?? #lgger daemon? in apache format
實驗:實現varnishd緩存基本功能
前期準備:
虛擬機2臺
varinishd服務器:192.168.30.10??? 系統版本:CentOS 7.4
node1:192.168.30.27????????? 系統版本:CentOS 7.4
varinish:
yum install varnish
systemctl start varnishd
此時訪問varnish的6081端口,顯示連接后端失敗
配置varnish:
vim /etc/varnish/default.vcl
varnish_reload acl
node1:
開啟WEB服務
echo backend Server node1 > /var/www/html/index.html
此時再次訪問192.168.30.10:6081,基本的varnish緩存功能就實現了
三、VCL語言與狀態引擎
相關概念:
”域“專有類型的配置語言;
state engine:狀態引擎;
VCL有多個狀態引擎,狀態之間存在相關性,但狀態引擎彼此間互相隔離;每個狀態引擎可使用return(x)
指明關聯至哪個下一級引擎;每個狀態引擎對應于vcl文件中的一個配置段,即為subroutine
vcl_hash –> return(hit) –> vcl_hit
varnish狀態引擎類型:
varnish 4.0:
????????????????? vcl_init
????????????????? vcl_recv
????????????????? vcl_hash
????????????????? vcl_hit
????????????????? vcl_pass
????????????????? vcl_miss
????????????????? vcl_pipe
????????????????? vcl_waiting
????????????????? vcl_purge
????????????????? vcl_deliver
????????????????? vcl_synth
????????????????? vcl_fini
??????????????????????????????????
????????????????? vcl_backend_fetch
????????????????? vcl_backend_response
????????????????? vcl_backend_error
vcl_recv的默認配置:
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);
}
}
Client Side:
vcl_recv, vcl_pass, vcl_hit, vcl_miss, vcl_pipe, vcl_purge, vcl_synth, vcl_deliver
vcl_recv:
hash:vcl_hash
pass: vcl_pass
pipe: vcl_pipe
synth: vcl_synth
purge: vcl_hash –> vcl_purge
vcl_hash:
lookup:
hit: vcl_hit
miss: vcl_miss
pass, hit_for_pass: vcl_pass
purge: vcl_purge
Backend Side:
vcl_backend_fetch, vcl_backend_response, vcl_backend_error
兩個特殊的引擎:
vcl_init:在處理任何請求之前要執行的vcl代碼:主要用于初始化VMODs;
vcl_fini:所有的請求都已經結束,在vcl配置被丟棄時調用;主要用于清理VMODs;
?格式:
(1) VCL files start with vcl 4.0;
(2) //, # and /* foo */ for comments;
(3) Subroutines are declared with the sub keyword; 例如sub vcl_recv { …};
(4) No loops, state-limited variables(受限于引擎的內建變量);
(5) Terminating statements with a keyword for next action as argument of the return() function, i.e.: return(action);用于實現狀態引擎轉換;
(6) Domain-specific;
Finite State Machine
(1) Each request is processed separately;
(2) Each request is independent from others at any given time;
(3) States are related, but isolated;
(4) return(action); exits one state and instructs Varnish to proceed to the next state;
(5) Built-in VCL code is always present and appended below your own VCL;
語法:
sub subroutine {
??????? …
}
if CONDITION {
??????? …
} else {
??????? …
}
return(), hash_data()
t-in Functions and Keywords
函數:
regsub(str, regex, sub)
regsuball(str, regex, sub)
ban(boolean expression)
hash_data(input)
synthetic(str)
Keywords:
call subroutine, return(action),new,set,unset
操作符:
==, !=, ~, >, >=, <, <=
邏輯操作符:&&, ||, !
變量賦值:=
示例1:obj.hits是內建變量,用于保存某緩存項的從緩存中命中的次數;
?? if (obj.hits>0) {
??????????????? set resp.http.X-Cache = “HIT via” + ” ” + server.ip;
??????? } else {
??????????????? set resp.http.X-Cache = “MISS from ” + server.ip;
??????? }
vim /etc/varnish/default.vcl
使用curl -I -s ?http:url 可以判斷是否緩存命中
示例2:判定curl類型的請求拒絕訪問
修改配置文件
vim /etc/varnish/default.vcl
調用配置文件
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
切換到另外一臺主機進行curl測試:
返回403錯誤狀態碼
示例3:判定admin相關的請求拒絕訪問
node1:
創建一個名稱為admin訪問目錄:
echo hello,world > /var/www/html/admin/index.html
systemctl reload httpd
正常訪問返回如下:
修改配置文件:
vim /etc/varnish/default.vcl
調用配置文件
再次訪問http://192.168.30.10:6081/admin/
示例4:強制對某類資源請求不檢查緩存
示例5:對于特定類型的資源,例如公開的圖片等,取消其私有標識,并強行設定其可以由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;
}
}
四、Varnish緩存修剪
緩存對象的修剪有兩種:
purge:指定刪除某條url的緩存
ban:指定刪除某類url的緩存
配置purge操作:
(1) 能執行purge操作
??? sub vcl_purge {
??????? return (synth(200,”Purged”));
??? }
(2) 何時執行purge操作
??? sub vcl_recv {?
??????? if (req.method == “PURGE”) {
??????????? return(purge);?
??????? }
??????? …
??? }
???????????????
添加此類請求的訪問控制法則:
acl purgers {
??????? “127.0.0.0”/8;
??????? “10.1.0.0”/16;
}
sub vcl_recv {
??????? if (req.method == “PURGE”) {
??????????????? if (!client.ip ~ purgers) {
??????????????????????? return(synth(405,”Purging not allowed for ” + client.ip));
??????????????? }
??????????????? return(purge);?
??????? }??????????????
??????? …????
}
示例:
修改配置:
緩存修剪測試:
如果擔心緩存修剪被其他人操作,也可添加ACL的訪問控制
當使用不再ACL范圍內的主機進行訪問時,返回結果如下:
而在ACL定義范圍內的主機則可正常使用PURGE修剪緩存
配置Banning操作:
(1) varnishadm:
?? ban <field> <operator> <arg>???
示例:
?? ban req.url ~ (?i)^/javascripts
(2) 在配置文件中定義,使用ban()函數;
示例:
if (req.method == “BAN”) {
??????? ban(“req.http.host == ” + req.http.host + ” && req.url == ” + req.url);
??????? # Throw a synthetic page so the request won’t go to the backend.
??????? return(synth(200, “Ban added”));
}??
curl -X BAN http://www.ilinux.io/test1.html
ban req.http.host==www.ilinux.io && req.url==/test1.html
五、Varnish負載均衡
如何設定使用多個后端主機:
backend default {
??????? .host = “172.16.100.6”;
??????? .port = “80”;
}
backend appsrv {
??????? .host = “172.16.100.7”;
??????? .port = “80”;
}
sub vcl_recv {???????????????????????
??????? if (req.url ~ “(?i)\.php$”) {
??????????????? set req.backend_hint = appsrv;
??????? } else {
??????????????? set req.backend_hint = default;
??????? }??????
???????
??????? …
}
nginx: proxy_pass
haproxy: use_backend
實驗:實現varnish的負載均衡
前期準備:
Varnish服務器:192.168.30.10??? 系統版本:CentOS 7.4
node1:192.168.30.27??? 系統版本:CentOS 7.4
node2:192.168.30.16??? 系統版本:CentOS 7.4
客戶端:192.168.30.18??? 系統版本:CentOS 7.4
具體步驟:
修改配置文件:
vim /etc/varnish/default.vcl
node1:
創建javascripts的web目錄,并創建文件test1-test6,內容分別也為test1-test6
node2:
創建javascripts的web目錄,并創建文件test1-test6,內容分別為node1-node6
客戶端進行測試訪問:
可看到輪詢算法調度已生效,當第二次進行訪問時,均緩存命中
也可實現基于cookie的會話粘性,及隨機性算法調度方式
配置格式如下:
六、后端服務器健康性狀態檢查
.probe:定義健康狀態檢測方法;
.url:檢測時要請求的URL,默認為”/”;
.request:發出的具體請求;
.request =
“GET /.healthtest.html HTTP/1.1”
“Host: www.magedu.com”
“Connection: close”
.window:基于最近的多少次檢查來判斷其健康狀態;
.threshold:最近.window中定義的這么次檢查中至有.threshhold定義的次數是成功的;
.interval:檢測頻度;
.timeout:超時時長;
.expected_response:期望的響應碼,默認為200;
健康狀態檢測的配置方式:
(1) probe PB_NAME? { }?
???????????? backend NAME = {???????
??????????????? .probe = PB_NAME;??????
??????????????? …
???????????? }
????????????
??????? (2) backend NAME? {????
??????????? ????.probe = {?????????????
??????????????????????? …????????????????????
??????????????? }
??????? }
設置后端的主機屬性:
???????? backend BE_NAME {
????????????????? …
????????????????? .connect_timeout = 0.5s;
????????????????? .first_byte_timeout = 20s;
????????????????? .between_bytes_timeout = 5s;
????????????????? .max_connections = 50;
???????? }
示例:
查看后端服務器健康性狀態:
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
手動設定BE主機的狀態:
sick:管理down;
healthy:管理up;
auto:probe auto;
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/103189