一、Varnish簡介:
Varnish是一款高性能的開源HTTP加速器,varnish項目是2006年發佈的第一個版本,現在很多門戶網站已經部署了varnish,並且反應都很好,甚至反應比squid還穩定,且效率更高,資源佔用更少,在功能上,它可以作爲反向代理服務器和緩存服務器使用,不過它的反向代理功能不如haproxy或者nginx性能強大,所以它的應用多數都在緩存服務器的場景下。
二、Varnish的核心引擎以及常用變量類型:
Varnish有9個核心引擎,用於處理用戶請求以及後端服務器響應的報文,當然處理的報文更多的目的是判斷是否需要緩存以及與緩存相關的特性或者是要處理的執行動作。在很多時候,我們需要從連貫的角度考慮數據流經這幾個引擎上的可能,需要考慮數據報文經由這些引擎時可能執行的流程,這有助於我們完整的編寫其配置文件,也有助於我們更好的理解Varnish內部的數據處理機制。
Varnish內部的核心引擎:
vcl_recv、vcl_pipe、vcl_pass、vcl_hash、vcl_hit、vcl_miss、vcl_fetch、vcl_deliver、vcl_error
Varnish中可用的內置變量:
請求到達時可用的內置變量
req.url、req.request、req.http.header、req.restarts、server.ip、server.port、server.hostname、client.ip、req.backend
向後端主機請求時可用的內置變量
bereq.url、bereq.request、bereq.http.header、bereq.connect_timeout、bereq.proto
從後端主機獲取到相應的object時可用的內置變量
beresp.response、beresp.status、beresp.http.header、beresp.backend.name、beresp.backend.ip、beresp.backend.port、beresp.ttl
二、Varnish的應用:
1、Varnish在作爲緩存服務器工作的同時,它的另外一個角色與Haproxy相同,也就是要作爲反向代理使用,而請求後端服務器數據時,請求者的身份是Varnish而不再是客戶端,也意味着在上游服務器的日誌記錄中記錄的請求者的信息是代理服務器的IP地址,這通常不是我們需要的,通常需要記錄的是真實的客戶端IP地址,如果要在後端服務器端記錄該地址,使用的方式如下:
首先需要定義後端的服務器信息,Varnish的配置文件如果是基於RPM包安裝的方式安裝的,爲/etc/varnish目錄下的default.vcl,如果後端主機爲172.16.103.2,那麼相應在配置文件中定義內容爲:
backend default { .host = "172.16.103.2"; .port = "80"; }
注意:在Varnish的配置文件中默認就是將客戶端的真實IP地址發送給服務器端,所以我們需要啓用Varnish的默認配置文件中vcl.req段的配置,然後修改的是後端服務器記錄日誌的格式就可以了。
sub vcl_recv { 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; } } return (lookup); }
修改後端服務器的httpd服務的配置文件保存日誌的格式爲:
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" combined
這樣在客戶端請求數據報文發給前端的Varnish主機時,如果沒有緩存,會將請求發往後端服務器,並記錄真實的客戶端IP地址,例如:
172.16.103.111 - - [26/Sep/2014:23:54:26 +0800] "GET /favicon.ico HTTP/1.1" 404 287 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36" -
2、當有些請求的資源不需要緩存時,可以在Varnish的配置文件中的vcl_recv段中使用如下的方式定義:
if (req.url ~ "^/test.html$") { return (pass);
語句的含義是使用正則表達式來匹配以/test.html開頭的uri,如果用戶請求的是這種類型的資源,就直接將請求發往後端主機,而不使用緩存,使用這種方式我們也可以測試客戶端的請求是否可以直接發往後端的服務器。測試效果如下:
3、當某些緩存資源需要清理時,我們需要執行PURGE操作,定義的方式如下:
這個操作可能出現的情況比較多,首先,因爲Varnish緩存的數據在實際的應用場景中會非常重要,不能隨意允許其他人連入直接刪除緩存的操作,所以要執行這種操作時,需要判斷用戶的身份,在Varnish的配置文件中,可以使用acl列表定義允許使用PURGE的用戶列表,然後在各個可能出現PURGE操作的執行引擎位置定義該操作的執行效果。示例如下:
acl purgers { "127.0.0.1"; "172.16.103.0"/24; }
sub vcl_recv { if (req.request == "PURGE") { if (client.ip !~ purgers) { error 405 "Method not allowed."; } return(lookup); } return (lookup); }
sub vcl_pass { if (req.request == "PURGE") { error 502 "PURGE on a passwd object"; } return (pass); }
sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged"; } return (deliver); }
sub vcl_miss { if (req.request == "PURGE") { purge; error 404 "Not in cache"; } return (fetch); }
這樣定義好之後,每當用戶發起PURGE請求時,數據報文在到達vcl.recv時會先判斷用戶的身份,如果用戶的身份與定義的acl中的規則匹配,則允許用戶執行後續的操作,後續的操作中如果用戶刪除的緩存條目存在,則顯示200返回碼,並顯示Purged,如果刪除的緩存條目不存在,則顯示錯誤404,並提示要刪除的條目不在緩存中,當用戶的數據報文如果經過vcl_pass時,由於是發往後端主機的,所以不可能有刪除緩存的可能性,所以會提示502錯誤。
具體刪除緩存條目時的刪除示例:
[root@node2 html]# curl -X PURGE http://172.16.103.1/index.html <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>200 Purged</title> </head> <body> <h1>Error 200 Purged</h1> <p>Purged</p> <h3>Guru Meditation:</h3> <p>XID: 1703226672</p> <hr> <p>Varnish cache server</p> </body> </html>
4、Varnish可以實現對後端服務器提供健康檢測的功能,定義的方式如下:
backend default { .host = "172.16.103.2"; .port = "80"; .probe = { .url = "/index.html"; .interval = 2s; .window = 8; .threshold = 2; } }
具體查看時可以使用telnet連接到Varnish使用其中的backend.list命令來查看後端服務器的健康狀況:
# varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 varnish> backend.list 200 Backend name Refs Admin Probe default(172.16.103.2,,80) 1 probe Healthy (no probe) web1(172.16.103.2,,80) 1 probe Healthy 8/8
5、當Varnish作爲反向代理時,其後端可以有多個服務器提供服務,在Varnish配置文件中可以定義多個後端的backend server同時還可以將多個服務器定義爲一個組,使用director關鍵字來定義,在處理引擎中需要用到各director時再調用即可,在定義director時,由於Varnish有負載均衡的效果,所以調度的時候有相應的算法,算法有兩種,分別的random和round-robin,配置示例:
backend web1 { .host = "172.16.103.2"; .port = "80"; .probe = { .url = "/index.html"; .interval = 2s; .window = 8; .threshold = 2; } } backend web2 { .host = "172.16.103.3"; .port = "80"; .probe = { .url = "/index.html"; .interval = 2s; .window = 8; .threshold = 2; } } acl purgers { "127.0.0.1"; "172.16.103.0"/24; } director webservers round-robin { { .backend = web1; } { .backend = web2; } }
定義好各後端的服務器及director之後,就可以在需要調用director的處理引擎段中調用director了,比如在vcl.recv段中定義:
sub vcl_recv { set req.backend = webservers;
這樣當數據請求報文到達Varnish主機時,會自動將數據請求報文依據定義的算法調度至後端的各服務器進行響應,同時,如果響應的結果可以緩存,那麼會有一份結果保存在Varnish中,之後再次請求時,會直接由Varnish響應之後的用戶請求。