現在,互聯網應用規模不斷擴大,應用不斷增多,網絡已經深刻到咱們生活的各個方面,給咱們的平常生活帶來極大方便,隨着信息系統的業務擴展,網站用戶增長,歷史數據不斷積累,業務不斷增加,系統的響應速度、請求的處理能力開始降低,CPU和磁盤IO處理能力會成爲瓶頸。php
若是在有限的硬件投入前提下,提升系統性能就成了主要解決問題手段,爲了提供高性能的web服務,可採用包括負載均衡、頁面靜態化、數據庫集羣、緩存等多種技術方案,其中,緩存方案是目前主流的性能優化方式,對於網站來講,有不少特定信息系統的請求都是重複冗餘的,咱們的系統常常在作重複的計算和傳輸着相同的內容。這也就意味着在有限的計算資源條件下,可經過緩存技術,大幅提升請求處理能力以及處理速度。css
緩存,又稱加速器,用於加速運行速度較快的設備與較慢設備之間的通訊。基於程序的運行具備局部性特徵其能實現加速的功能:html
緩存有效與否,是經過緩存命中率來衡量的。緩存命中,意味着在請求某資源時,在緩存中找到該資源,並響應給客戶端。前端
緩存命中率的計算方式:hits/(hits+misses) (0-1)(命中的/命中的+沒有命中的)nginx
緩存是把以前訪問到的數據及其周邊的數據放置於具備更快速度的、效率更高的設備中來完成加速。使用緩存以後, 資源的請求與響應過程由client–>server–>client改變爲client–>cache[–>server]–>client。若在緩存中沒有查找到相應的資源,將會由緩存向server請求該資源,這一過程,會形成額外的開銷,若換成命中率太低,則會形成資源的浪費。所以,提升緩存的命中率是必然的。web
時間局部性:一個數據被訪問過以後,可能很快會被再次訪問到;算法
空間局部性:一個數據被訪問時,其周邊的數據也有可能被訪問到(好比:nginx定義一個緩存,首先要定義一個緩存路徑和空間大小,當緩存空間滿了,就會使用lru算法(最近最少使用算法),將最近最少訪問的緩存數據給清理掉,那麼剩下的就是訪問最多的數據,也就是熱點數據)數據庫
緩存空間耗盡:LRU,最近最少使用;(Least recently used,最近最少使用)
緩存過時:到了緩存時間後失效(失效以後不必定會被刪除,要看你怎樣定義)
資源緩存:page cache ,static cache;
瀏覽器緩存控制機制有兩種:HTML Meta標籤 vs. HTTP頭信息
瀏覽器緩存機制,其實主要就是HTTP協議定義的緩存機制(如: Expires;Cache-control等)。可是也有非HTTP協議定義的緩存機制,如使用HTMLMeta 標籤,Web開發者能夠在HTML頁面的<head>節點中加入<meta>標籤,代碼以下:
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
1.0版本的Expires策略:Expires是Web服務器響應消息頭字段,在響應http請求時告訴瀏覽器在過時時間前瀏覽器能夠直接從瀏覽器緩存取數據,而無需再次請求。不過Expires 是HTTP 1.0的東西,如今默認瀏覽器均默認使用HTTP 1.1,因此它的做用基本忽略。Expires 的一個缺點就是,返回的到期時間是服務器端的時間,這樣存在一個問題,若是客戶端的時間與服務器的時間相差很大(好比時鐘不一樣步,或者跨時區),那麼偏差就很大,因此在HTTP 1.1版開始,使用Cache-Control: max-age=秒替代。
1.1版本的Cache-control策略(重點關注):Cache-Control與Expires的做用一致,都是指明當前資源的有效期,控制瀏覽器是否直接從瀏覽器緩存取數據仍是從新發請求到服務器取數據。只不過Cache-Control的選擇更多,設置更細緻,若是同時設置的話,其優先級高於Expires。
請求報文的頭部(比較經常使用的是no-cache和max-age)
響應頭部的Etag和請求頭部的If-None-Match作比對
響應頭部的Last-Modified和請求頭部的If-Modified-Since作對比
Last-Modified/If-Modified-Since要配合Cache-Control使用。
(1) Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。
(2) If-Modified-Since:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
Etag/If-None-Match也要配合Cache-Control使用。
(1) Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的惟一標識(生成規則由服務器以爲)。Apache中,ETag的值,默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後獲得的。
(2)If-None-Match:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304
你可能會以爲使用Last-Modified已經足以讓瀏覽器知道本地的緩存副本是否足夠新,爲何還須要Etag(實體標識)呢?HTTP1.1中Etag的出現主要是爲了解決幾個Last-Modified比較難解決的問題:
(1) Last-Modified標註的最後修改只能精確到秒級,若是某些文件在1秒鐘之內,被修改屢次的話,它將不能準確標註文件的修改時間
(2)若是某些文件會被按期生成,當有時內容並無任何變化,但Last-Modified卻改變了,致使文件無法使用緩存
(3)有可能存在服務器沒有準確獲取文件修改時間,或者與代理服務器時間不一致等情形Etag是服務器自動生成或者由開發者生成的對應資源在服務器端的惟一標識符,可以更加準確的控制緩存。Last-Modified與ETag是能夠一塊兒使用的,服務器會優先驗證ETag,一致的狀況下,纔會繼續比對Last-Modified,最後才決定是否返回200或者304。
常見的緩存服務開源解決方案有varnish、nginx、squid、ats等。Varnish是一款高性能的開源HTTP加速器,挪威最大的在線報紙 Verdens Gang 使用3臺Varnish代替了原來的12臺Squid,性能比之前更好。
Varnish 的做者Poul-Henning Kamp是FreeBSD的內核開發者之一,varnish項目是2006年發佈的第一個版本0.9.距今已經有十年了,此文檔以前也提過varnish還不穩定,那是2007年時候編寫的,通過varnish開發團隊和網友們的辛苦耕耘,如今的varnish已經很健壯。不少門戶網站已經部署了varnish,而且反應都很好,甚至反應比squid還穩定,且效率更高,資源佔用更少。相信在反向代理,web加速方面,varnish已經有足夠能力代替squid。
一、Varnish的穩定性很高,二者在完成相同負荷的工做時,Squid服務器發生故障的概率要高於Varnish,由於使用Squid要常常重啓;
2.Varnish訪問速度更快,由於採用了"Page Cache"技術,全部緩存數據都直接從內存讀取(映射),而squid是從硬盤讀取,於是Varnish在訪問速度方面會更快;
三、Varnish能夠支持更多的併發鏈接,由於Varnish的TCP鏈接釋放要比Squid快,於是在高併發鏈接狀況下能夠支持更多TCP鏈接;
四、Varnish能夠經過管理端口,使用正則表達式批量的清除部分緩存,而Squid是作不到的;
五、squid屬因而單進程使用單核CPU,但Varnish是經過fork形式打開多進程來作處理,因此能夠合理的使用全部核來處理相應的請求
varnish主要運行兩個進程:Management進程和Child進程(也叫Cache進程)。
Management進程主要實現應用新的配置、編譯VCL、監控varnish、初始化varnish以及提供一個命令行接口等。Management進程會每隔幾秒鐘探測一下Child進程以判斷其是否正常運行,若是在指定的時長內未獲得Child進程的迴應,Management將會重啓此Child進程。
Child進程包含多種類型的線程,Varnish依賴"工做區(workspace)"以下降線程在申請或修改內存時出現競爭的可能性。在varnish內部有多種不一樣的工做區,其中最關鍵的當屬用於管理會話數據的session工做區。
Worker線程:child進程會爲每一個會話啓動一個worker線程,此worker線程真正來管理緩存,構建響應報文,所以,在高併發的場景中可能會出現數百個worker線程甚至更多;
yum 安裝:一般是在線安裝,好處是安裝方式簡單,不易出錯;經常使用的安裝yum源爲epel
源碼包安裝:是先將 Varnish 的源碼下載下來,在本身的系統裏編譯生成可執行文件,而後執行,好處是由於是在本身的系統上編譯的,更符合本身系統的性能,也就是說在本身的系統上執行 Varnish 服務性能效率更好。(推薦)
命令行管理工具程序: /usr/bin/varnishadm
主配置文件:/etc/varnish/default.vcl
性能配置文件:/etc/varnish/varnish.params
Unit file: /usr/lib/systemd/system/varnish.service(centos7)
Init.file :/etc/init.d/varnish (centos6)
Varnish的主配置文件路徑通常在/etc/varnish/default.vcl下(yum安裝)
VCL,Varnish Configuration Language 是varnish配置緩存策略的工具,它是一種基於"域"(可想象與iptables的幾個鏈,也就是相似鉤子函數)的簡單編程語言,它支持有限的算術運算和邏輯運算操做、容許使用正則表達式進行字符串匹配、容許用戶使用set自定義變量、支持if判斷語句,也有內置的函數和變量等。
使用VCL編寫的緩存策略一般保存至.vcl文件中,其須要編譯成二進制的格式後才能由varnish調用。事實上,整個緩存策略就是由幾個特定的子例程如vcl_recv、vcl_hash等組成,它們分別在不一樣的位置(或時間)執行,若是沒有事先爲某個位置自定義子例程,varnish將會執行默認的定義。
VCL策略在啓用前,會由management進程將其轉換爲C代碼,然後再由gcc編譯器將C代碼編譯成二進制程序。編譯完成後,management負責將其鏈接至varnish實例,即child進程。正是因爲編譯工做在child進程以外完成,它避免了裝載錯誤格式VCL的風險。所以,varnish修改配置的開銷很是小,其能夠同時保有幾份尚在引用的舊版本配置,也可以讓新的配置即刻生效。編譯後的舊版本配置一般在varnish重啓時纔會被丟棄,若是須要手動清理,則可使用varnishadm的vcl.discard命令完成。
設置爲1表示當使用systemctl reload varnish時,會自動從新裝載vcl的配置文件,也就是可以讓新的配置生效
VARNISH_VCL_CONF=/etc/varnish/default.vcl
varnish服務監聽的地址,默認是監聽在本機全部可用的地址上
#varnish監聽的端口,由於varnish要做爲web服務器的反代進行工做時,才能將http的內容緩存,通常要將其改成80端口,可是實際生產環境中,varnish通常是處於前端調度器的後面,因此能夠在前端調度器上將調度的端口改成此處的端口也能夠
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
varnish管理接口監聽的地址,監聽在127.0.0.1表示只容許從本機登陸進行管理
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_SECRET_FILE=/etc/varnish/secret
varnish管理時的祕鑰文件(用varnish管理內存是一種危險的操做,是須要認證的,而這個認證是基於一個文件內的一串字符,因此要指定認證文件)
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"
varnish緩存時,使用哪一種存儲方式對緩存內容進行存儲,本處是指使用file文件方式,存在
/var/lib/varnish/varnish_storage.bin文件中,總共使用1G大小的空間若是要使用內存緩存,則能夠定義爲:
"malloc,400M"在不少生產環境仍是使用file,可是將文件放在固態硬盤,若是但願性能更好點,放在PCI-E的固態硬盤fution-IO
3.persistent經過文件持久存儲,persistent,path,size 前二者在重啓後緩存都會消失,persistent能夠永久保存緩存,但還爲開發階段
若是後端服務器沒有指明緩存內容的TTL時間,則varnish自身爲緩存定義的TTL時間
VCL有多個狀態引擎,狀態之間存在相關性,但狀態引擎彼此間互相隔離;每一個狀態引擎可以使用return(x)指明關聯至哪一個下一級引擎;每一個狀態引擎對應於vcl文件中的一個配置段
vcl_recv:接受用戶請求進varnish的入口的引擎,接受到結果以後,利用return(lookup),將請求轉交給vcl_hash引擎進行處理
vcl_hash:接受到用戶請求後,對用戶請求的URL進行hash計算,根據請求的首部信息,以及hash結果進行下一步處理的引擎
vcl_hit:通過vcl_hash引擎處理後,發現用戶請求的資源本地有緩存,則vcl_hash引擎經過return(hit)將請求交給vcl_hit引擎進行處理,vcl_hit引擎處理後將請求交給vcl_deliver引擎,vcl_deliver引擎構建響應報文,響應給用戶
vcl_miss:通過vcl_hash引擎處理後,發現用戶請求的資源本地沒有緩存,則vcl_hash引擎經過return(miss)將請求交給vcl_miss引擎進行處理
vcl_purge:通過vcl_hash引擎處理後,發現請求是對緩存的內容進行修剪時,則經過return(purge)交給vcl_purge引擎進行處理,vcl_purge引擎處理後,利用vcl_synth引擎將處理的結果告知給用戶
vcl_pipe:通過vcl_hash引擎處理後,發現用戶請求的報文varnish沒法理解,則經過return(pipe),將請求交給vcl_pipe引擎,pipe引擎直接將請求交給後端真實服務器
vcl_pass:當請求通過vcl_hash處理後,發現請求報文不讓從緩存中進行響應或其餘緣由沒辦法查詢緩存,則由return(pass)或return(hit-for-pass)交由vcl_pass引擎進行處理
vcl_backend_fetch:當發現緩存未命中或由vcl_pass傳遞過來的某些不能查詢緩存的請求,交由vcl_backend_fetch引擎處理,vcl_backend_fetch引擎會向後端真實web服務器發送請求報文,請求對應的資源
vcl_backend_response:當後端發送響應報文到varnish後,會由vcl_backend_resonse引擎進行處理,如:判斷響應的內容是否可緩存,若是能緩存,則緩存下來後,交給vcl_deliver引擎,若是不能緩存,則直接交給vcl_deliver引擎,vcl_deliver引擎構建響應報文給客戶端
vcl_init(初始化,定義服務器集羣):在處理任何請求以前要執行的vcl的代碼,主要用於初始化VMOD,可用在後端主機有多臺時,藉助此引擎完成多臺主機的負載均衡效果
vcl_fini:全部的請求都已經結束,在vcl配置被丟棄時調用;主要用於清理VMOD(通常不用配)
用戶請求–>vcl_recv–>vcl_hash–>vcl_hit–>vcl_deliver–>響應給用戶
用戶請求–>vcl_recv–>vcl_hash–>vcl_miss–>vcl_backend_fetch–>後端服務器接受請求發送響應報文–>vcl_backend_response–>vcl_deliver
用戶請求–>vcl_recv–>vcl_hash–>vcl_miss–>vcl_pass–>vcl_backend_fetch–>後端服務器接受請求發送響應報文–>vcl_backend_response–>vcl_deliver–>響應給用戶
用戶請求–>vcl_recv–>vcl_hash–>vcl_pass–>vcl_backend_fetch–>後端服務器接受請
求發送響應報文–>vcl_backend_response–>vcl_deliver–>響應給用戶
用戶請求–>vcl_recv–>vcl_pipe–>交給後端服務器
<1>配置文件第一個非註釋行必須是vcl 4.0,標明此vcl配置文件是基於vcl4.0版本
<5>使用終止語句return(XXX),沒有返回值,僅僅是標明下一步交給哪一個狀態引擎,沒有走默認
<6>域專用,語句用{ }括起來,用sub聲明,指明爲哪一段的專用代碼,如:sub vcl_recv{…},可理解爲一個配置段
<8> 每一個變量有其能使用的引擎的位置,可理解爲變量由其可用的配置段
<9>操做符:=(賦值)、==(等值比較)、~(模式匹配)、!(取反)、&&(邏輯與)、||(邏輯或)、>(大於)、>=(大於等於)、<(小於)、<=(小於等於)
VCL提供了幾個函數來實現字符串的修改,添加bans,重啓VCL狀態引擎以及將控制權轉回Varnish等。
ban(expression):清除能被表達式匹配的全部緩存對象
ban_url(regex):清除全部其URL可以由regex匹配的緩存對象;
hash_data(str):對指定的字符串作hash計算後的結果,例如:hash_data(req.url)對請求報文的url進行哈希運算
return(): 當某VCL域運行結束時將控制權返回給Varnish,並指示Varnish如何進行後續的動做;其能夠返回的指令包括:lookup、hash、hit、miss、pass、pipe、hit_for_pass、purge等;但某特定域可能僅能返回某些特定的指令,而非前面列出的所有指令;
req.*:req.開頭的變量,由客戶端發來的http請求相關的變量:req.method 表示客戶端的請求方法
bereq.* :bereq.開頭的變量,varnish主機在向後端真實服務器發送http請求報文時的相關變量
beresp.*:beresp.開頭的變量,由後端真實服務器發來的http響應報文中的某些首部信息相關的變量,通常
是在vcl_backend_response或vcl_backend_fenth引擎中調用
resp.*:resp.開頭的變量,由varnish響應給客戶端的響應報文相關的變量
obj.* :obj.開頭的變量,對存儲在緩存空間中的緩存對象屬性的引用變量。obj開頭的變量都是隻讀的
client.,server.,storage.*:可用在全部面向客戶端一側的引擎中,也就是vcl_recv、vcl_pipe、vcl_hash
、vcl_pass、vcl_purge、vcl_miss、vcl_hit、vcl_deliver、vcl_synth中
if (req.url ~ "(?i)^/(login|admin)") {
if (req.http.User-Agent ~ "(?i)curl") {
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
if (req.http.X-Fowarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;
set req.http.X-Forwarded-For = client.ip;
.threshhold:最近.window中定義的這麼次檢查中至有.threshhold定義的次數是成功的;
.expected_response:指望的響應碼,默認爲200;
.url= "/.healthcheck.html" #得先建立這個測試頁面;
set req.backend_hint = appsrv;
set req.backend_hint = default;
-S /etc/varnish/secret -T 127.0.0.1:80
vcl.show [-v] <configname>:查看指定的配置文件的詳細信息,可看默認配置;
1>、varnishstat – Varnish Cache statistics 各類計數器
# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
# varnishstat -l -f MAIN -f MEMPOOL
2>、varnishtop – Varnish log entry ranking 將日誌文件中相關數據逆序排序
-1 Instead of a continously updated display, print the statistics once and exit.
-i taglist,能夠同時使用多個-i選項,也能夠一個選項跟上多個標籤;篩選
varnishtop -i RespStatus 查看響應碼
3>、varnishlog – Display Varnish logs 查看實時日誌
4>、 varnishncsa – Display Varnish logs in Apache / NCSA combined log format 標準日
sub vcl_backend_response { # 自定義緩存文件的緩存時長,即TTL值
if (bereq.url ~ "\.(jpg|jpeg|gif|png)$") {
if (bereq.url ~ "\.(html|css|js)$") {
# if (beresp.http.Set-Cookie) { # 定義帶Set-Cookie首部的後端響應不緩存,直接返回給客戶端
# 以上配置表示varnish將會將失效的緩存對象再多保留30分鐘,此值等於最大的req.grace值便可;
# 而根據後端主機的健康情況,varnish可向前端請求提供30分鐘過時內容