1. 程式人生 > >緩存varnish的管理及配置詳解

緩存varnish的管理及配置詳解

啟動 一個 hint 單位 quad spec int rom try

一 工作原理

在當前主流的Web服務架構體系中,Cache擔任著越來越重要的作用。常見的基於瀏覽器的C/S架構,Web Cache更是節約服務器資源的關鍵。而最近幾年由FreeBSD創始人之一Kamp開發的varnish更是一個不可多得的Web Cache Server。嚴格意義上說,Varnish是一個高性能的反向代理軟件,只不過與其出色的緩存功能相比,企業更願意使用其搭建緩存服務器。同時,由於其工作在Web Server的前端,有一部分企業已經在生產環境中使用其作為舊版本的squid的替代方案,以在相同的服務器成本下提供更好的緩存效果,Varnish更是作為CDN緩存服務器的可選服務之一。

Varnish主要有以下幾點特性:
1.緩存位置:可以使用內存也可以使用磁盤。如果要使用磁盤的話推薦SSD做RAID1
2.日誌存儲:日誌也存儲在內存中。存儲策略:固定大小,循環使用
3.支持虛擬內存的使用。
4.有精確的時間管理機制,即緩存的時間屬性控制。
5.狀態引擎架構:在不同的引擎上完成對不同的緩存和代理數據進行處理。可以通過特定的配置語言設計不同的控制語句,以決定數據在不同位置以不同方式緩存。類似於netfilter中的鉤子,在特定的地方對經過的報文進行特定規則的處理。
6.緩存管理:以二叉堆格式管理緩存數據,做到數據的及時清理。


二 基本架構

1. 狀態引擎

技術分享

2.內部處理流程

技術分享

三 配置詳解

1. 簡單安裝

[[email protected] ~]# yum install varnish -y

2. 配置詳解

[[email protected] ~]# cd /etc/varnish


配置default.vcl配置文件

[[email protected] varnish]# cat default.vcl
# 使用varnish版本4的格式.
vcl 4.0;
# 加載後端輪詢模塊
import directors;
#######################健康檢查策略區域###########################
# 名為www_probe的健康檢查策略
probe www_probe {
 .request =
 "GET /html/test.html HTTP/1.1"    # 健康檢查url為/html/test.html 協議為http1.1
# "Host: www.xiaxiaodie.com"        # 訪問的域名為www.xiaxiaodie.com
 "Connection: close";        # 檢查完關閉連接
#其他參數 如 超時時間 檢查間隔 等 均使用默認
}
##################################################################
#######################配置後端區域################################
backend backend_15 {
 .host = "172.18.67.15";
 .port = "80";
 .probe = www_probe; # 使用名為www_probe的健康檢查策略
}
backend backend_16 {
 .host = "172.18.67.16" 
 .port = "80";
 .probe = www_probe; # 使用名為www_probe的健康檢查策略
}
#默認後端
backend default {
 .host = "172.18.67.15" 
 .port = "80";
}
###################################################################
# 配置後端集群事件
sub vcl_init {
# 後端集群有4種模式 random, round-robin, fallback, hash
 # random 隨機
 # round-robin 輪詢
 # fallback 後備
 # hash 固定後端 根據url(req.http.url) 或 用戶cookie(req.http.cookie) 或 用戶session(req.http.sticky)(這個還有其他要配合)
 # 把backend_15 和 backend_16配置為輪詢集群 取名為www_round_robin
 new www_round_robin = directors.round_robin();
 www_round_robin.add_backend(backend_15);
 www_round_robin.add_backend(backend_16);
 # 把backend_15 和 backend_16配置為隨機選擇集群 取名為www_random
 new www_random = directors.random();
 www_random.add_backend(backend_15,10);  # 設置backend_15後端的權重為10
 www_random.add_backend(backend_16,5);   # 設置backend_16後端的權重為5
 # 把backend_15 和 backend_16配置為固定後端集群 取名為www_hash 在recv調用時還需要添加東西 看recv例子
 new www_hash = directors.hash();
 www_hash.add_backend(backend_15,1);        # 設置backend_15後端的權重為1
 www_hash.add_backend(backend_16,1);        # 設置backend_16後端的權重為1
}
#定義允許清理緩存的IP
acl purge {
# For now, I‘ll only allow purges coming from localhost
 "127.0.0.1";
 "localhost";
}
# 請求入口 這裏一般用作路由處理 判斷是否讀取緩存 和 指定該請求使用哪個後端
sub vcl_recv {
 # 域名為 www.xiaxiaodie.com 的請求 指定使用名為www_round_robin的後端集群  在集群名後加上 .backend() 如只使用單獨後端 直接寫後端名字即可 如 = backend_16;
 if (req.http.host ~ "node2") {
  set req.backend_hint = www_round_robin.backend();
 }
 # 使用固定後端集群例子 使用名為www_hash的集群
 if (req.http.host ~ "3g.xiaxiaodie.com") {
 set req.backend_hint = www_hash.backend(req.http.cookie);  # 根據用戶的cookie來分配固定後端 可以指定其他分配規則
 }
 # 其他將使用default默認後端
 # 把真實客戶端IP傳遞給後端服務器 後端服務器日誌使用X-Forwarded-For來接收
 if (req.restarts == 0) {
  if (req.http.X-Forwarded-For) {
   set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
  } else {
   set req.http.X-Forwarded-For = client.ip;
  }
 }
 # 匹配清理緩存的請求
 if (req.method == "PURGE") {
  # 如果發起請求的客戶端IP 不是在acl purge裏面定義的 就拒絕
  if (!client.ip ~ purge) {
   return (synth(405, "This IP is not allowed to send PURGE requests."));
  }
  # 是的話就執行清理
  return (purge);
 }
 # 如果不是正常請求 就直接穿透沒商量
 if (req.method != "GET" &&
  req.method != "HEAD" &&
  req.method != "PUT" &&
  req.method != "POST" &&
  req.method != "TRACE" &&
  req.method != "OPTIONS" &&
  req.method != "PATCH" &&
  req.method != "DELETE") {
   /* Non-RFC2616 or CONNECT which is weird. */
  return (pipe);
  }
 # 如果不是GET和HEAD就跳到pass 再確定是緩存還是穿透
 if (req.method != "GET" && req.method != "HEAD") {
  return (pass);
 }
 # 緩存通過上面所有判斷的請求 (只剩下GET和HEAD了)
 return (hash);
}
# pass事件
sub vcl_pass {
# 有fetch,synth or restart 3種模式. fetch模式下 全部都不會緩存
return (fetch);
}
# hash事件(緩存事件)
sub vcl_hash {
# 根據以下特征來判斷請求的唯一性 並根據此特征來緩存請求的內容 特征為&關系
 # 1. 請求的url
 # 2. 請求的servername 如沒有 就記錄請求的服務器IP地址
 # 3. 請求的cookie
 hash_data(req.url);
 if (req.http.host) {
 hash_data(req.http.host);
 } else {
 hash_data(server.ip);
 }
 # 返回lookup , lookup不是一個事件(就是 並非指跳去sub vcl_lookup) 他是一個操作 他會檢查有沒有緩存 如沒有 就會創建緩存
 return (lookup);
}
# 緩存命中事件 在lookup操作後自動調用 官網文檔說 如沒必要 一般不需要修改
sub vcl_hit {
 # 可以在這裏添加判斷事件(if) 可以返回 deliver restart synth 3個事件
 # deliver  表示把緩存內容直接返回給用戶
 # restart  重新啟動請求 不建議使用 超過重試次數會報錯
 # synth    返回狀態碼 和原因 語法:return(synth(status code,reason))
 # 這裏沒有判斷 所有緩存命中直接返回給用戶
 return (deliver);
}
# 緩存不命中事件 在lookup操作後自動調用 官網文檔說 如沒必要 一般不需要修改
sub vcl_miss {
 # 此事件中 會默認給http請求加一個 X-Varnish 的header頭 提示: nginx可以根據此header來判斷是否來自varnish的請求(就不用起2個端口了)
 # 要取消此header頭 只需要在這裏添加 unset bereq.http.x-varnish; 即可
 # 這裏所有不命中的緩存都去後端拿 沒有其他操作 fetch表示從後端服務器拿取請求內容
 return (fetch);
}
# 返回給用戶的前一個事件 通常用於添加或刪除header頭
sub vcl_deliver {
 # 例子
 # set resp.http.*    用來添加header頭 如 set resp.http.xiaxiaodie = "haha"; unset為刪除
 # set resp.status     用來設置返回狀態 如 set resp.status = 404;
 # obj.hits        會返回緩存命中次數 用於判斷或賦值給header頭
 # req.restarts    會返回該請求經歷restart事件次數 用戶判斷或賦值給header頭
 # 根據判斷緩存時間來設置xiaxiaodie-Cache header頭
 if (obj.hits > 0) {
  set resp.http.xiaxiaodie_Cache = "cached";
 } else {
 set resp.http.xiaxiaodie_Cache = "uncached";
 }
 #取消顯示php框架版本的header頭
 unset resp.http.X-Powered-By;
 #取消顯示nginx版本、Via(來自varnish)等header頭 為了安全
 unset resp.http.Server;
 unset resp.http.X-Drupal-Cache;
 unset resp.http.Via;
 unset resp.http.Link;
 unset resp.http.X-Varnish;
 #顯示請求經歷restarts事件的次數
 set resp.http.xiaxiaodie_restarts_count = req.restarts;
 #顯示該資源緩存的時間 單位秒
 set resp.http.xiaxiaodie_Age = resp.http.Age;
 #顯示該資源命中的次數
 set resp.http.xiaxiaodie_hit_count = obj.hits;
 #取消顯示Age 為了不和CDN沖突
 unset resp.http.Age;
 #返回給用戶
 return (deliver);
}
#處理對後端返回結果的事件(設置緩存、移除cookie信息、設置header頭等) 在fetch事件後自動調用
sub vcl_backend_response {
 #後端返回如下錯誤狀態碼 則不緩存
 if (beresp.status == 499 || beresp.status == 404 || beresp.status == 502) {
  set beresp.uncacheable = true;
 }
 #如請求php或jsp 則不緩存
 if (bereq.url ~ "\.(php|jsp)(\?|$)") {
  set beresp.uncacheable = true;
 #php和jsp以外的請求
 } else {
 #如請求html 則緩存5分鐘
  if (bereq.url ~ "\.html(\?|$)") {
   set beresp.ttl = 300s;
   unset beresp.http.Set-Cookie;
  #其他緩存1小時 如css js等
  }else{
  set beresp.ttl = 1h;
  unset beresp.http.Set-Cookie;
  }
 }
 #開啟grace模式 表示當後端全掛掉後 即使緩存資源已過期(超過緩存時間) 也會把該資源返回給用戶 資源最大有效時間為6小時
 set beresp.grace = 6h;
 #返回給用戶
 return (deliver);
}

配置varnish.params配置文件

[[email protected] varnish]# vim varnish.params
# 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
# 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=80
# Admin interface listen address and port
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"
# 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"

3.簡單管理工具

[[email protected] varnish]# varnishadm -S secret -T 127.0.0.1:6082
200        
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,3.10.0-327.el7.x86_64,x86_64,-smalloc,-smalloc,-hcritbit
varnish-4.0.4 revision 386f712
Type ‘help‘ for command list.
Type ‘quit‘ to close CLI session.
help
200        
help [<command>]
ping [<timestamp>]
auth <response>
quit
banner
status
start
stop
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
param.show [-l] [<param>]
param.set <param> <value>
panic.show
panic.clear
storage.list
vcl.show [-v] <configname>
backend.list [<backend_expression>]
backend.set_health <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
ban.list

四 訪問測試

[[email protected] varnish]# systemctl start varnish.service

技術分享

緩存varnish的管理及配置詳解