WEB快取控制機制與varnish簡介
- 2020 年 4 月 2 日
- 筆記
在說到快取varnish前,我們首先來了解下對於web服務快取到底是什麼?它有哪些特點,基礎原理是什麼?
http是web應用協議,通常我們說的一次http事務,不外乎就是客戶端請求,服務端響應,通常我們是這樣去理解http一次事務的過程;其實對於web伺服器來說,一個客戶端訪問服務端的某資源時,往往客戶端的請求沒有到達真正提供web服務的伺服器上,就被響應了,這是為什麼呢?我們知道一個WEB站點在提供對外訪問的頁面上在一定時間內都不會發生變化,而對於這些不經常變化的資源,訪問又特別大的情況,如果所有客戶端的請求都到真正提供WEB服務的伺服器上請求資源,可以想像,對於提供web服務的伺服器所在網路是需要一個巨大頻寬才能夠足以支撐並發很多用戶去訪問;所以我們的站點不應該也不能夠讓所有的客戶端直接訪問後端真正的web伺服器;在現實生活中我們訪問某度的網站,感覺很快的樣子,其實這背後就是快取的作用;那什麼是快取呢?所謂快取,對於http協議來說,就是把那些經常被訪問到的熱區資源,通過某種機制把它存放在離客戶端最近的地方,客戶端訪問該資源時,直接從快取中響應即可,這樣的機制就是快取;簡單講快取就是把熱區資源放到離客戶端最近的地方,方便客戶端訪問時,直接從快取的資源響應給客戶端,這樣一來就解決了,後端真正提供web服務的伺服器所在網路頻寬的問題,同時也加速了客戶端的訪問請求;對於http協議來說,程式的運行具有時間局部性和空間局部性特徵,所謂時間局部性特徵就是一個數據被訪問過之後,可能很快會被第二次訪問到;空間局部性指的是一個數據被訪問時,其周邊的數據也有可能別訪問到;如果我們把這些很受歡迎的資源(可能被多次訪問到的資源)和其周圍的一些資源存起來,放到離客戶端最近的地方,這樣一來,大多數的客戶端訪問我們的站點就會被快取響應,能夠真正到達後端真正提供web服務的伺服器上的客戶端請求就大大減少;這就是快取的作用,它一方面是減少後端伺服器的壓力,同時加速了客戶端的訪問;通常情況下快取是有生命周期的,什麼意思呢?就是說快取不是說一直存放在哪裡不變的,它是有時效性的,如果一個快取項過期了,那麼該快取就會被識別為失效的快取項,對於失效的快取通常會有一個快取管理機制處理該快取項,最常見的處理方式就是把失效的快取項直接清理出去,除此之外在http1.1協議中,對於這種失效的快取來講,通常客戶端請求該資源時,一看快取時間過期了,那麼此時快取伺服器會向後端或上游伺服器發送一個條件式請求問下真正的伺服器,說“我這裡的快取失效了,請問你那裡的資源的時間戳改變了嗎?如果沒有改變我就用我這裡的快取響應給客戶端咯”,如果後端伺服器用304響應快取伺服器,就說明後端伺服器上對於該資源在時間戳上沒有發生改變,快取伺服器收到304的響應後,它會把自己的快取生命周期往後延長一段時間,同時把客戶端的請求從該快取中響應給客戶端;如果後端伺服器響應的是200的狀態碼,快取伺服器收到該響應,會把後端伺服器的響應資源快取到自己本地,然後在從快取中響應客戶端請求;這就是所謂的條件是請求;對於快取來說,快取的命中至關重要,所謂命中就表示客戶端訪問某資源,能夠從快取中響應,那麼我們就說該次http事務被快取命中;一個快取如果命中率極低,那麼我們就會認為該快取快取的意義不大,所以一個快取項快取是否有意義,關鍵還要看它的命中率如何;命中率有兩種,第一種是基於頁面數量來進行衡量的,我們叫做頁面命中率;一個是基於頁面的體積進行衡量的,我們叫這種為位元組命中率;同時快取又分私有快取和公有快取,所謂私有快取就表示某客戶端的私有數據,通常該快取只能被某一客戶端命中,所以通常情況下,這種私有快取是在瀏覽器上存儲;而公有快取是指沒有私有屬性的快取,對於所有客戶端都可用,我們這裡通常說的快取都是指這種公有快取;
了解了快取的大概介紹,我們再來看看在http協議中快取是如何被控制的;http1.0中的快取控制機制吧!在http1.0協議中,快取控制機制是通過後端伺服器的響應首部expires給定一個到期時間,來明確告訴客戶端該資源在給定的這個時間內都是有效的;我們知道對於一個站點來說,它可能是全球的,這樣一來如果通過絕對時間來控制快取,很明顯,如果客戶端的時間和服務端的時間有誤差,很有可能存在一部分客戶端訪問某資源時,得到服務端響應expires首部的時間在客戶端就是失效的。這樣一來對於這部分客戶端很明顯快取對於他們是無緣的;所以在http1.0中這種絕對時間控制機制對於那種全球性的網站是不太適合的;為了解決這樣的困境,在http1.1協議中引入了相對時間控制機制,這種快取控制機制是利用響應報文首部的cache-control特定值maxage或s-maxage的值控制的;什麼意思呢?就是客戶端請求某一資源時,服務端會明確告訴客戶端該資源可快取,快取的時間是多長時間,這樣一來就不存在客戶端系統時間和伺服器時間不兼容或者有誤差的情況導致快取天前或延後失效的問題;maxage指定的時間適用於那些公有快取和私有快取,而s-maxage只適用於公有快取;在如今普片http1.1或2.0協議中為了兼容http1.0,通常這兩種時間控制機制都是共同存在的;我們可以隨便打開一網站來看看這兩個首部;
提示:以上響應首部就是告訴瀏覽器下次請求該資源時,如果在expires首部給定的時間之前訪問該資源,都會從快取中直接響應;如果我們客戶端時間和服務端的時間有誤差或不兼容,那麼在本次請求的後7776000秒之前,如果該資源再次被訪問都從快取中直接響應;也就說在本次訪問到下次訪問的時間如果小於7776000秒就直接從快取中響應;
在http1.1協議中除了上面基於時間的快取控制機制外,還引入了條件式請求的機制來判斷快取有效方式,在上面我們已經大概闡述過條件式請求的邏輯;這裡再大概的描述下,所謂條件式請求就是客戶端每訪問一次服務端的資源,都會去問真正的伺服器該資源的時間戳改變了沒有,如果沒有改變服務端就用304響應告訴客戶端沒有變,從而客戶端的請求就會被快取直接響應;如果服務端上的對應資源發生了變化,那麼服務端會以200的響應碼告訴客戶端資源的時間戳發生改變了,同時把改變後的資源發送給客戶端,客戶端收到服務端的響應後,它會把新的資源快取起來,然後再用新的資源響應客戶端;其實對於這種基於時間戳的形式來判斷資源是否改變,其實是不是很精準的;比如伺服器上的某一資源在一秒鐘變化了8次,如果基於時間戳來判斷資源是否改變(精確到秒),很可能服務端會告訴客戶端資源沒變,其實服務端上的資源改變了,為了解決這種問題,在http1.1還引進了擴展標記的控制機制,這種控制機制和基於時間戳控制機制流程都是一樣的,只是在基於時間戳控制是以資源的時間戳來判斷該資源是否發生改變,而擴展標記控制機制是以資源的校驗碼來判別資源是否發生改變,很明顯後者對於資源是否發生改變的控制更加精準,當同時對服務端的CPU消耗也就更多一點,因為每一次響應都要把對應資源校驗下,拿到其校驗碼進行和客戶端的校驗碼對比;在http1.1中基於時間戳的條件是請求表現形式在客戶端請求首部if-modified-since,表示告訴服務自從某某時間後服務端對應資源發生變化了嗎,響應報文中以last-modified首部來告訴客戶端伺服器上對應資源的最近修改時間戳,如果響應報文中的時間戳比請求報文中的時間戳新,那麼客戶端就會收到200的響應碼,如果響應報文中的時間戳小於或等於請求報文中的時間戳,那麼客戶端就會收到304的響應碼,意思就是指資源沒有發生變化,該快取可以繼續使用;通常客戶端請求某資源服務端會用last-modified首部告訴客戶端資源的時間戳,以便判斷資源是否發生改變;基於擴展標記的方式在http1.1協議中的表現形式就是在請求報文首部以if-none-match來告訴服務端客戶端請求資源的校驗,響應報文首部用Etag首部告訴客戶端對應資源的校驗碼,如果兩者相等表示資源沒有發生改變,對應響應碼就是304,如果兩者不等,表示資源發生了改變,響應碼就是200;擴展標記機制通過對比校驗碼的形式來判斷資源是否發生改變;
提示:從上面的響應報文和請求報文首部的值來對比,很容易判斷該資源沒有發生改變;通常情況下我們只是基於某一種機制來控制快取就好,如果你想精度高一點,我們直接使用擴展標記機制即可,如果精度沒有那麼高,可以使用基於資源時間戳的機制來控制就好;
了解了http協議中的快取控制機制,我們這裡在著重說一下cache-control在請求報文中的值,和響應報文中的值代表意義(如何處理快取內容)
http1.1協議中請求首部cache-control的值如果是“no-cache”即表示告訴快取伺服器本次請求不要用快取里的數據響應;
提示:以上請求就表示告訴快取伺服器不要用快取響應本次請求,所以我們能看到本次請求的狀態碼是200而非304;通常我們使用瀏覽器對資源強刷,請求報文中cache-control的值就是”no-cache”
當然對於請求報文中cache-control的值還有多,但是用的比較少,這裡就不過多強調其他值的意思,我們著中來說說http協議1.1中,響應首部cache-control的值;在響應報文首部中cache-control的值主要是告訴快取伺服器或快取系統怎麼處理快取數據;比如在響應報文首部cache-control的值是“public”就表示該數據可以被公用快取系統或伺服器快取,對於私有快取伺服器或系統當然也是可以快取該數據;如果響應首部cache-control的值是“private”就表示告訴快取系統該數據只能用於私有快取系統中,公有快取系統不能快取該數據;如果是“no-cache”就表示告訴快取系統該數據可快取,當在響應給客戶端之前需要做條件式請求進行快取有效性驗證;“no-store”表示告訴快取系統該資源或數據不允許存儲在快取中;“must-revalidate”這個意思同“no-cache”一樣表示可快取,但響應必須做條件式請求驗證快取的有效性;“max-age”表示告訴快取系統該資源或數據的快取時長是多少秒;“s-maxage”表示告訴快取系統該資源在公有快取系統上的生命時長(該值表示指定公有快取系統或者代理快取伺服器上的快取時長);
在了解了http1.1協議中是如何控制快取,接下來我們聊一聊針對web服務快取應用的開源實現;對於web應用快取系統開源實現有兩款軟體squid和varnish,這兩款軟體有點像apache httpd 和nginx 關係,他們分別是不同年代的產品,對於varnish是來講,可以說它是squid的替代品,因為varnish相比之下要比squid性能更穩定,響應速度更快,支援的並發連接更多等等;
varnish的官方站點是http://www.varnish-cache.org,它和其他主流開源產品類似有community和enterprise兩個版本,前者免費,後者你懂的;varnish它是一款高性能的http快取伺服器,其程式架構如下
提示:varnish程式架構如上圖,主要由四部分組成,配置介面VCL、manager進程、cache進程和共享記憶體日誌;其中manager進程主要是管控cache進程的,配置文件的編譯並載入,而cache進程包含多種類型的執行緒,每個執行緒處理一類事務,如command line處理命令行命令的,log/stats記錄日誌和統計數據,accept用於接收請求,storage/hashing用於管理存儲和快取中的鍵的,backend communication用於與後端伺服器進行通訊用的,object expiry用於管理快取項和過期時間的;對於varnish的日誌,為了更高效的提供服務,它的日誌是記錄在共享記憶體的,而共享記憶體的大小是固定的,日誌不會越記越大,它採取的是輪轉機制,日誌記錄滿了就覆蓋最前邊的日誌,是得日誌最大只能佔用給定大小的空間;這也是varnish的日誌管理的獨特地方,如果我們需要保存日誌,需要周期性的去共享記憶體中把日誌讀出來保存到文件中即可;當然用於日誌管理的工具有很多,varnish提供了五種工具,分別用於管理日誌的,其中varnishlog是把共享記憶體中的日誌記錄成varnish原始格式的日誌,varnishncsa是把共享記憶體中的日誌記錄成http combined格式的日誌,varnishtop就是用來對共享記憶體中的日誌排序用到的工具,varnishhist用於查看日誌歷史資訊,varnishstat用於統計數據的;varnish的配置文件有兩個,一個是定義varnish程式自身的工作特性(/etc/varnish/varnish.params),一個是定義快取工作特性(/etc/varnish/default.vcl),通常情況下配置個child/cache執行緒的快取策略,需要用專用的配置語言vcl(varnish configuration lanuage),通常這種配置文件在定義好後,不能直接使用,需要用vcl 編譯器將其編譯成C程式碼,然後通過c編譯器編譯編譯成共享對象,提供給子進程中的執行緒鏈接載入使用;
varnish安裝
[root@test_node1-centos7 ~]# yum install -y varnish
提示:安裝可以是編譯也可以是yum安裝,如果是yum安裝,需要提前把epel倉庫配好,varnish包它來源epel倉庫;
varnish的程式環境說明
[root@test_node1-centos7 ~]# rpm -ql varnish /etc/logrotate.d/varnish /etc/varnish /etc/varnish/default.vcl /etc/varnish/varnish.params /run/varnish.pid /usr/bin/varnishadm /usr/bin/varnishhist /usr/bin/varnishlog /usr/bin/varnishncsa /usr/bin/varnishstat /usr/bin/varnishtest /usr/bin/varnishtop /usr/lib/systemd/system/varnish.service /usr/lib/systemd/system/varnishlog.service /usr/lib/systemd/system/varnishncsa.service /usr/sbin/varnish_reload_vcl /usr/sbin/varnishd ……省略部分內容……
提示:/etc/varnish/varnish.params: 配置varnish服務進程的工作特性,例如監聽的地址和埠,快取機制;/etc/varnish/default.vcl:配置各Child/Cache執行緒的快取策略;/usr/sbin/varnishd是主程式,/usr/bin/varnishadm是命令行管理工具;/usr/bin/varnishhist、varnishlog、varnishncsa、varnishstat、varnishtop都是共享記憶體日誌交互工具;/usr/bin/varnishtest是測試工具程式;/usr/sbin/varnish_reload_vcl是vcl配置文件重載程式;/usr/lib/systemd/system/varnish.service是varnish服務unit文件;/usr/lib/systemd/system/varnishlog.service和varnishncsa.service是日誌持久服務unit文件;
以上就是http協議中的快取控制機制說明和varnish程式架構和環境的簡單說明,後續本人會持續更新varnish系列使用說明;有興趣的朋友可以關注、評論,共同探討和學習;