① 瀏覽器緩存(http緩存)
瀏覽器緩存有兩種:強制緩存和協商緩存
向瀏覽器緩存中查找請求結果,根據【緩存規則】決定是否使用該結果。
強制緩存失效後,攜帶緩存標識請求伺服器,伺服器根據緩存標識判斷是否使用緩存
當瀏覽器向伺服器發送請求的時候,伺服器會將緩存規則放入HTTP響應的報文的HTTP頭中和請求結果一起返回給瀏覽器(ps:下文說的時間點均為類似:Sat Aug 14 2021 11:01:52,秒級)
兩個欄位:Expires和Cache-Control,優先順序:Cache-Control > Expires,客戶端比較時間
Expires :HTTP/1.0,返回值為【到期時間點】,再次請求,客戶端的時間< Expires,直接用緩存(ps:客戶端與伺服器端時間可能存在誤差,出問題)
Cache-Control :HTTP/1.1,有以下欄位
Last-Modified / If-Modified-Since 和 Etag / If-None-Match,優先順序Etag > Last-Modified,伺服器比較時間
Last-Modified(服務端返回客戶端) / If-Modified-Since(客戶端傳入服務端) :兩個值相同,表示:資源文件在伺服器最後被修改的時間【時間點】。
Etag(服務端返回客戶端) / If-None-Match(客戶端傳入服務端) ,兩個值相同,為當前資源文件的一個唯一標識(由伺服器生成)
Etag什麼時候用
雅虎禁用了Etag:因為ETag的值和伺服器有關,那麼對於同樣的文件,可能下次請求的時候是發給不同的伺服器,結果也會重新發送數據,所以就會影響網頁載入速度,增加伺服器的壓力(但Last-Modified也與伺服器有關)
主要解決的問題:
瀏覽器的每個tab都是一個進程
兩個緩存的地方 from memory cache(內存緩存) 和 from disk cache(硬碟緩存) ,讀取順序為memory > disk
② 系列分享之瀏覽器、本地DNS緩存篇
我們在使用瀏覽器訪問互聯網資源時,想獲取指定的服務和信息。首先就要了解瀏覽器是如何定位到我們的站點的。輸入一個域名(如:www.jd.com)瀏覽器會首先從自身的緩存中查詢是否有歷史域名對應的IP並且有效,如果有就使用該緩存通過IP直接訪問到指定的站點。如果沒有則查詢本地的Host緩存,如果有就使用本地的緩存直接訪問站點,沒有則向本地DNS伺服器發起請求查詢,如果本地DNS服務也沒有找到,則向公網DNS服務發起查詢請求獲取對應的有效IP,並返回緩存到瀏覽器和本地緩存中,供後續請求使用。
DNS記錄會有一個ttl值(time to live),單位是秒,意思是這個記錄最大有效期是多少。操作系統緩存會參考ttl值,但是不完全等於ttl值,而瀏覽器DNS緩存的時間跟ttl值無關,每種瀏覽器都使用一個固定值。
DNS查詢請求類型:
1、權威答復:權威答復是返回給客戶的正向答復,並且設置了DNS消息中的權威位。此答復代表從具有權威的DNS伺服器處發出。
2、正向答復:正向答復包含了匹配客戶端解析請求的資源記錄。
3、參考答復:參考答復只在DNS伺服器工作在迭代模式下使用,包含了其他有助於客戶端解析請求的信息。例如,當DNS伺服器不能為客戶端發起的解析請求找到某個匹配值時,則向DNS客戶端發送參考回復,告訴它有助於解析請求的信息。
4、否定答復:否定答復指出權威伺服器在解析客戶端的請求時可能遇到了以下兩種情況之一:
權威DNS伺服器報告客戶端查詢的名字不存在;
權威DNS伺服器報告存在對應的名字,但是不存在指定類型的資源記錄。
DNS伺服器解析返回IP分配策略與客戶端對域名IP選擇策略,無論正向答復還是否定答復,DNS客戶端都將結果保存在自己的本地緩存中
瀏覽器緩存:
瀏覽器在獲取網站域名的實際IP地址後會對其IP進行緩存,減少網路請求的損耗。每種瀏覽器都有一個固定的DNS緩存時間。
參考瀏覽器DNS緩存時間:
本地緩存:
每種操作系統都有自己的DNS緩存時間控制。
1、Windows DNS默認值是MaxCacheTTL,它的默認值是86400s,也就是一天。
2、MacOS遵循DNS協議中的TTL,根據各種網路協議不同對不同的域名採用不同的緩存時間策略。在IPv4包頭中TTL是一個8 bit欄位,它位於IPv4包的第9個位元組。
參考本地DNS緩存時間:
在命令行執行nslookup指令可以看到一個域名對應的IP地址,並且可以幫助我們判斷是否有DNS劫持。隨便解析一個網站,比如
www.jd.com 應該返回的是正常的地址
然後再解析一個不存在的網站,比如123123.aaaa.com.cn如果返回的結果是
DNS request timed out.
timeout was 2 seconds.
那麼證明你的DNS沒有被劫持。
如果返回的結果是一個IP地址,比如說網通的返回地址是230.xxx.xxx.xxx,那麼證明你的DNS被劫持了。
通過了解瀏覽器、本地緩存可以幫助我們更好的為用戶服務。
1、大型的互聯網公司都有IP流量監控,當發生網路故障或劫持時可以第一時間發現。
2、頁面是我們與用戶面對面溝通的渠道和方式,當我們的網頁和服務呈現在用戶面前時,我們要了解我們提供的服務是如何影響到用戶的體驗的,比如我們前端頁面的JS、CSS等文件的動態版本號處理方式結合緩存是如何變化的,每次發版會對什麼樣的用戶有影響,都需要嚴謹。
3、機房內部的各個應用程序服務,比如Zookeeper、Redis、RPC、DB在DNS緩存變化時,可能引起的網路抖動,是否會對用戶請求造成影響,也是我們必須要注意的問題。
③ Okhttp解析(五)緩存的處理
大家好,之前我們講解了Okhttp網路數據請求相關的內容,這一節我們講講數據緩存的處理。本節按以下內容講解Okhttp緩存相關的內容。
緩存的使用場景很多,通過它可以將數據通過一定的規則存儲起來,再次請求數據的時候就可以快速從緩存中讀取了,緩存有以下優勢。
HTTP本身提供了一套緩存相關的機制。這套機制定義了相關的欄位和規則,用來客戶端和服務端進行緩存相關的協商,如響應的數據是否需要緩存,緩存有效期,緩存是否有效,伺服器端給出指示,而客戶端則根據服務端的指示做具體的緩存更新和讀取緩存工作。http緩存可以分為兩類:
強制緩存,在緩存數據未失效的情況下,可以直接使用緩存數據,有兩個欄位Expires和Cache-Control用於標明失效規則。
表示過期時間,由服務端返回。那麼下次請求數據時,判斷這個Expires過期時間是否已經過了,如果還沒有到過期時間,則使用緩存,如果過了過期時間,則重新請求伺服器的數據。Expires格式如下:
不過因為伺服器和客戶端的時間並不是同步的,用一個絕對時間作為過期的標記並不是很明智,所以HTTP1.1之後更多的是Cache-Control,它的控制更加靈活。
表示緩存的控制,有服務端返回。它有以下幾個取值:
默認情況下是private,也就是不能共享的。Cache-Control格式如下:
對比緩存,表示需要和服務端進行相關信息的對比,由伺服器決定是使用緩存還是最新內容,如果伺服器判定使用緩存,返回響應嗎304,判定使用最新內容,則返回響應碼200和最新數據。對比緩存的判定欄位有兩組:
ETag表示資源的一種標識信息,用於標識某個資源,由服務端返回,優先順序更高。格式如下:
然後客戶端再次請求時,加入欄位If-None-Match,格式如下:
服務端收到請求的該欄位時(之前的Etag值),和資源的唯一標識進行對比,如果相同,說明沒有改動,則返回狀態碼304,如果不同,說明資源被改過了,則返回狀態碼200和整個內容數據。
Last-Modified表示資源的最近修改時間,由服務端返回,優先順序更低。格式如下:
Last-Modified
由伺服器返回,表示響應的數據最近修改的時間。
If-Modified-Since
由客戶端請求,表示詢問伺服器這個時間是不是上次修改的時間。如果服務端該資源的修改時間小於等於If-Modified-Since指定的時間,說明資源沒有改動,返回響應狀態碼304,可以使用緩存。如果服務端該資源的修改時間大於If-Modified-Since指定的時間,說明資源又有改動了,則返回響應狀態碼200和最新數據給客戶端,客戶端使用響應返回的最新數據。
Last-Modified欄位的值(服務端返回的資源上次修改時間),常常被用於客戶端下次請求時的If-Modified-Since欄位中。
HTTP的緩存規則是優先考慮強制緩存,然後考慮對比緩存。
Okhttp緩存相關的類有如下:
要開啟使用Okhttp的緩存其實很簡單,只需要給OkHttpClient對象設置一個Cache對象即可,創建一個Cache時指定緩存保存的目錄和緩存最大的大小即可。
那麼下面我們來看看Okhttp緩存執行的大概流程
Okhttp的緩存流程分為讀取緩存和存儲緩存兩個過程,我們分別分析。
讀取使用緩存的流程從HttpEngine的sendRequest發送請求開始。
接下來我們分析
從Cache的get方法開始。它按以下步驟進行。
如果存在緩存的話,在指定的緩存目錄中,會有兩個文件「****.0」和「****.1」,分別存儲某個請求緩存的響應頭和響應體信息。(「****」是url的md5加密值)對應的ENTRY_METADATA響應頭和ENTRY_BODY響應體。緩存的讀取其實是由DiskLruCache來讀取的,DiskLruCache是支持Lru(最近最少訪問)規則的用於磁碟存儲的類,對應LruCache內存存儲。它在存儲的內容超過指定值之後,就會根據最近最少訪問的規則,把最近最少訪問的數據移除,以達到總大小不超過限制的目的。
接下來我們分析CacheStrategy緩存策略是怎麼判定的。
直接看CacheStrategy的get方法。緩存策略是由請求和緩存響應共同決定的。
接來下我們看看CacheControl類里有些什麼。
可以發現,它就是用於描述響應的緩存控制信息。
然後我們再看看Okhttp存儲緩存是怎麼進行的。
存儲緩存的流程從HttpEngine的readResponse發送請求開始的。
可以看到這里先通過maybeCache寫入了響應頭信息,再通過cacheWritingResponse寫入了響應體信息。我們再進去看Cache的put方法實現。
我們繼續看Cache的writeTo方法,可以看到是寫入一些響應頭信息。
到這里Okhttp緩存的讀取和存儲流程我們就清楚了。可以說,緩存的使用策略基本都是按照HTTP的緩存定義來實現的,所以對HTTP緩存相關欄位的理解是很重要的。然後關於DiskLruCache是如何管理緩存文件的,這個其實也很好理解,首先的原則就是按照LRU這種最近最少使用刪除的原則,當總的大小超過限定大小後,刪除最近最少使用的緩存文件,它的LRU演算法是使用LinkedHashMap進行維護的,這樣來保證,保留的緩存文件都是更常使用的。具體實現大家可以分析DiskLruCache和LinkedHashMap的實現原理。
④ 認識HTTP----緩存篇
本文內容大多參考 《圖解HTTP》一書
所以講緩存為什麼要先扯代理伺服器?別急,讓我們看一下一個請求的簡單示意圖。
我們看到客戶端(用戶)發送了一個請求並不是直接發給源伺服器的而是經過了代理伺服器,然後經由代理伺服器再發送給源伺服器,響應也同樣遵循這個順序。
那麼代理伺服器在這中間擔任了什麼角色?
緩存是指代理伺服器或客戶端本地磁碟內保存的資源副本。利用緩存可減少對源伺服器的訪問,因此也就節省了通信流量和通信時間。
緩存伺服器是代理伺服器的一種,並歸類在緩存代理類型中。換句話說,當代理轉發從伺服器返回的響應時,代理伺服器將會保存一份資源的副本。
緩存伺服器的優勢在於利用緩存可避免多次從源伺服器轉發資源。因此客戶端可就近從緩存伺服器上獲取資源,而源伺服器也不必多次處理相同的請求了。
即便緩存伺服器和客戶端內有緩存,也不能每次都給我返回緩存吧,如果是這樣,源伺服器更新了我也不知道,因為我每次都是看緩存的資源。
為了解決這個問題,針對緩存設計了時效性的概念:
即使存在緩存,也會因為客戶端的要求、緩存的有效期等因素,向源伺服器確認資源的有效性。若判斷緩存失效,緩存伺服器將會再次從源伺服器上獲取「新」資源。
緩存不僅可以存在於緩存伺服器內,還可以存在客戶端瀏覽器中。以Internet Explorer 程序為例,把客戶端緩存稱為臨時網路文件(Temporary Internet File)。
瀏覽器緩存如果有效,就不必再向伺服器請求相同的資源了,可以直接從本地磁碟內讀取。
另外,和緩存伺服器相同的一點是,當判定緩存過期後,會向源伺服器確認資源的有效性。若判斷瀏覽器緩存失效,瀏覽器會再次請求新資源。
Pragma 是HTTP/1.1 之前版本的歷史遺留欄位,僅作為與HTTP/1.0的向後兼容而定義。
規范定義的形式唯一,如下所示。
Pragma: no-cache
該首部欄位屬於通用首部欄位,但只用在客戶端發送的請求中。客戶端會要求所有的中間伺服器不返回緩存的資源。
通過指定首部欄位Cache-Control 的指令,就能操作緩存的工作機制。
可用的指令按請求和響應分類如下所示:
public指令
Cache-Control: public
當指定使用public 指令時,則明確表明其他用戶也可利用緩存。
private指令
no-store指令
Cache-Control: no-store
當使用no-store 指令時,暗示請求(和對應的響應)或響應中包含機密信息。
因此,該指令規定緩存不能在本地存儲請求或響應的任一部分。
ps:從字面意思上很容易把no-cache誤解成為不緩存,但事實上no-cache代表不緩存過期的資源,緩存會向源伺服器進行有效期確認後處理資源,也許稱為do-not-serve-from-cache-without-revalidation更合適。no-store 才是真正地不進行緩存,請讀者注意區別理解。
s-maxage指令
Cache-Control: s-maxage=604800 //(單位:秒)
s-maxage 指令的功能和max-age 指令的功能相同, 它們的不同點是s-maxage 指令只適用於供多位用戶使用的公共緩存伺服器(這里指代理伺服器)。也就是說,對於向同一用戶重復返回響應的伺服器來說,這個指令沒有任何作用。
另外,當使用s-maxage 指令後,則直接忽略對Expires 首部欄位及max-age 指令的處理。
max-age指令
cache-extension token
Cache-Control: private, community="UCI"
通過 cache-extension 標記(token),可以擴展Cache-Control 首部欄位內的指令。
如上例,Cache-Control 首部欄位本身沒有community 這個指令。藉助extension tokens 實現了該指令的添加。如果緩存伺服器不能理community 這個新指令,就會直接忽略。因此,extension tokens 僅對能理解它的緩存伺服器來說是有意義的。
If-Unmodified-Since: Thu, 03 Jul 2012 00:00:00 GMT
首部欄位If-Unmodified-Since 和首部欄位If-Modified-Since 的作用相反。它的作用的是告知伺服器,指定的請求資源只有在欄位值內指定的日期時間之後,未發生更新的情況下,才能處理請求。如果在指定日期時間後發生了更新,則以狀態碼412 Precondition Failed 作為響應返回。
ps:Last-Modified 存在一定問題,如果在伺服器上,一個資源被修改了,但其實際內容根本沒發生改變,會因為Last-Modified時間匹配不上而返回了整個實體給客戶端(即使客戶端緩存里有個一模一樣的資源)。
首部欄位If-None-Match 屬於附帶條件之一。它和首部欄位If-Match 作用相反。用於指定If-None-Match 欄位值的實體標記(ETag)值與請求資源的ETag 不一致時,它就告知伺服器處理該請求。
在GET 或HEAD 方法中使用首部欄位If-None-Match 可獲取最新的資源。因此,這與使用首部欄位If-Modified-Since 時有些類似。
不與伺服器確認,而是直接使用瀏覽器緩存的內容。其中響應內容和之前的響應內容一模一樣,例如其中的Date時間是上一次響應的時間。
F5的作用和直接在URI輸入欄中輸入然後回車是不一樣的,F5會讓瀏覽器無論如何都發一個HTTP Request給Server,即使先前的響應中有Expires頭部。
Ctrl+F5要的是徹底的從Server拿一份新的資源過來,所以不光要發送HTTP request給Server,而且這個請求裡面連If-Modified-Since/If-None-Match都沒有,這樣就逼著Server不能返回304,而是把整個資源原原本本地返回一份,這樣,Ctrl+F5引發的傳輸時間變長了,自然網頁Refresh的也慢一些。
Cache-Control 是 HTTP1.1 才有的,不適用於 HTTP1.0,而 Expires 既適用於 HTTP1.0,也適用於 HTTP1.1,所以說在大多數情況下同時發送這兩個頭會是一個更好的選擇,當客戶端兩種頭都能解析的時候,會優先使用 Cache-Control。
二者都是通過某個標識值來請求資源, 如果伺服器端的資源沒有變化,則自動返回 HTTP 304 (Not Changed)狀態碼,內容為空,這樣就節省了傳輸數據量。當資源變化後則返回新資源。從而保證不向客戶端重復發出資源,也保證當伺服器有變化時,客戶端能夠得到最新的資源。
其中Last-Modified使用文件最後修改作為文件標識值,它無法處理文件一秒內多次修改的情況,而且只要文件修改了哪怕文件實質內容沒有修改,也會重新返回資源內容;ETag作為「被請求變數的實體值」,其完全可以解決Last-Modified頭部的問題,但是其計算過程需要耗費伺服器資源。
Expires和Cache-Control都有一個問題就是服務端的修改,如果還在緩存時效里,那麼客戶端是不會去請求服務端資源的(非刷新),這就存在一個資源版本不符的問題,而強制刷新一定會發起HTTP請求並返回資源內容,無論該內容在這段時間內是否修改過;而Last-Modified和Etag每次請求資源都會發起請求,哪怕是很久都不會有修改的資源,都至少有一次請求響應的消耗。
對於所有可緩存資源,指定一個Expires或Cache-Control max-age以及一個Last-Modified或ETag至關重要。同時使用前者和後者可以很好的相互適應。
前者不需要每次都發起一次請求來校驗資源時效性,後者保證當資源未出現修改的時候不需要重新發送該資源。而在用戶的不同刷新頁面行為中,二者的結合也能很好的利用HTTP緩存控制特性,無論是在地址欄輸入URI然後輸入回車進行訪問,還是點擊刷新按鈕,瀏覽器都能充分利用緩存內容,避免進行不必要的請求與數據傳輸。
做法很簡單,就是把可能會更新的資源以版本形式發布,常用的方法是在文件名或參數帶上一串md5或時間標記符:
可以看到上面的例子中有不同的做法,有的在URI後面加上了md5參數,有的將md5值作為文件名的一部分,有的將資源放在特性版本的目錄中。
那麼在文件沒有變動的時候,瀏覽器不用發起請求直接可以使用緩存文件;而在文件有變化的時候,由於文件版本號的變更,導致文件名變化,請求的url變了,自然文件就更新了。這樣能確保客戶端能及時從伺服器收取到新修改的文件。通過這樣的處理,增長了靜態資源,特別是圖片資源的緩存時間,避免該資源很快過期,客戶端頻繁向服務端發起資源請求,伺服器再返回304響應的情況(有Last-Modified/Etag)。
⑤ 緩存Cache-Control
首先附上前面提到的一張圖:
根據上面的這張圖,來說http協議中的緩存,也就是cache-control將會格外清晰。
Cache-Control包括哪些特性呢?
第一,可緩存性:public private no-cache 。可緩存性指http的response進過的哪些地方可以進行緩存。public指在response返回經過的任何地方都可以緩存,包括代理伺服器,客戶端等,這樣下次請求將不會到達服務端而直接返回response;private則表示只有返回的瀏覽器才可以進行緩存;no-cache則表示不可直接用緩存,而是先要到伺服器端進行驗證。
第二,到期:max-age=<seconds> ,代表緩存的時間(秒); s-maxage=<seconds> ,專門為代理伺服器設置,如果與max-age同時返回,則瀏覽器會讀取max-age,而代理伺服器則會讀取s-maxage這個設置; max-stale=<seconds> ,代表在max-age過期後,如果存在max-stale,而且其時間沒有過期,則表示仍然可以用緩存,max-stale只在request發起端設置是有用的,又因為瀏覽器不會幫助我們帶上這個頭,所以客戶端是瀏覽器的時候這個max-stale是用不到的。
第三,重新驗證:must-revalidate和proxy-revalidate ,這兩個表示緩存過期時間到達以後,必須要到服務端重新請求和重新驗證,這兩個屬性在瀏覽器也不怎麼出現。
第四,其他,no-store ,表示本地和代理伺服器都不可以用緩存,必須去重新獲取; no-transform ,告訴代理伺服器不要對返回的body進行處理,比如壓縮等(代理伺服器比如nginx等可以不遵守,但是這個是規范,最好遵守)。
下面附上做的幾個簡單的例子來加深對上面的理解 。例子中通過查看對文件script.js的緩存情況說明問題。
執行node server.js,觀察瀏覽器network如下圖(這里注意,瀏覽器的Disable cache沒有勾選,否則會默認忽略Cache-Control的設置):
立刻重新刷新瀏覽器,則network中出現下圖:
此時我們可以看見這事size一欄是from memory cache,因為我們設置max-age為20s,在這個期間即使我改變script.js的內容,瀏覽器仍然會用memory裡面的內容,而得不到更新。很顯然實際開發中,如果出現這樣的問題,是很可怕的。同時如果每次去後端請求response,又會使網頁很慢, 實際中max-age往往要設置很大 ,表示在本地保存很久的時間,那麼下次請求的Time為0。那麼實際開發中,如何去解決這兩者的矛盾呢?就是通過改變url的方法, 在請求的文件名後面加上根據內容生成的哈希值 (刷新瀏覽器緩存的方案),這樣實際請求的 url將會改變,那麼自然就會去重新請求,如果後端的文件沒有更新,也就是url沒有變,則自然會在緩存中讀取,則不需要經過網路傳輸,則速度是很快的,用戶體驗是很好的。 network一欄中,這里Size的兩個值,上面表示傳輸時候的大小,下面表示實際的大小(上面的可進行壓縮Gzip傳輸,但是不曉得header可不可以壓縮,貌似http2中支持頭壓縮),傳輸時的大小比實際的大,因為加上了頭信息。Time的兩個值,上面一行表示從請求開始到接受完最後一個byte為止的時間。下面一行是Latency,代表從請求接受完到讀取該資源第一個byte之間的等待時間。
上圖是查找緩存的過程。
如果Cache-Control中max-age的值設置很大,那麼一直用本地的緩存肯定是不可取的。所以除了給文件名後面加上哈希碼之外的方法,我們可以通過每次去後端詢問是否文件有所改動?那麼如何來實現這個過程呢?首先在Cache-Control中設置no-cache,同時遵從實際情況我們把max-age設置很大。更改servr.js如下:
打開network,多次刷新仍然如下:
說明此時已經不在緩存中讀取了,即使我們的max-age設置很大,這是因為我們設置了no-cache。所以每次我們都不會直接使用緩存了。那麼如何發揮no-cache的作用呢,還需要配合資源驗證,資源驗證在http中主要有兩個頭:Last-Modified和Etag。這個內容介紹在-資源驗證Last-Modified和Etag中介紹。
⑥ centosdns緩存時間
centosdns緩存時間24小時。根據查詢相關資料信息顯示,centos對dns伺服器緩存時間是86400秒,一小時等於3600秒,因此是24小時,com對dns伺服器緩存時間是48小時。通過centos客戶端可以查詢緩存的進度。
⑦ http緩存過程
註:http 緩存只能緩存 get 方式請求的資源
緩存是指 代理伺服器 或 客戶端本地磁碟 內保存的資源副本。利用緩存可減少對源伺服器的訪問,因此也就節省了通信流量和通信時間。
緩存伺服器是代理伺服器的一種,並歸類在緩存代理類型中。換句話說, 當代理轉發從伺服器返回的響應時,代理伺服器將會保存一份資源的副本 。
緩存伺服器的優勢在於利用緩存可避免多次從源伺服器轉發資源。因 此客戶端可就近從緩存伺服器上獲取資源,而源伺服器也不必多次處 理相同的請求了。
瀏覽器緩存分 強制緩存 和 協商緩存 ,分別使用的欄位前者是Expires和Cach-control,後者是 Etag 和 Last-modified。
Expires (http/1.0):設的是資源的過期時間(絕對時間),瀏覽器判斷這次請求的時候是不是超過這個日期,沒超的話就直接讀取緩存中的資源,不向伺服器發請求。
Pragma :欄位值為「no-cache」的時候,會通知客戶端不要對該資源讀緩存,即每次都得向伺服器發一次請求才行。但是這種禁用緩存的形式作用不是那麼太大:1. 僅有IE才能識別這段meta標簽含義,其它主流瀏覽器僅能識別「Cache-Control: no-store」的meta標簽。2. 在IE中識別到該meta標簽含義,並不一定會在請求欄位加上Pragma,但的確會讓當前頁面每次都發新請求,但是僅限頁面,頁面上的資源則不受影響。
如果Pragma和Expires一起出現的話,Pragma的優先順序是高的。
Cach-Control (http/1.1):緩存控制 示例:
Cache-Control 有三種屬性:緩沖能力、過期時間和二次驗證。
緩沖能力:
過期時間:
二次驗證:
Expires使用的是服務端時間,可能出現客戶端和服務端時間不同步,導致本地緩存無用或無法過期。
Max-Age使用的是客戶端本地時間的計算,不會出現這個問題,推薦Max-Age。
如果同時啟用了Cache-Control和Pragma ,Expires,Cache-Control優先順序高。
Last-Modified / If- Modified-Since (http/1.0):判斷資源最後修改時間,只要這個日期改變了就不使用緩存。瀏覽器的頭部是If- Modified-Since,服務端的是Last-Modified,如果兩個匹配,代表伺服器資源未改變,服務端不會返回資源實體,只返回頭部,通知瀏覽器使用緩存。
缺點:可能有些文件會周期性地改變日期,但是內容其實沒變,但是該欄位只判斷最後修改時間,
E-tag / If-None-Match (http/1.1):Etag 是伺服器針對請求的資源文件生成的唯一標識,只要文件內容沒變化,則Etag值不變,克服了 Last-Modified / If- Modified-Since 的缺點。瀏覽器的頭部是If-None-Match,服務端的是E-tag,如果兩個匹配,代表內容未改變,通知瀏覽器使用緩存。
Etag 缺點:不適用於分布式系統 ,因為每個伺服器上的 Etag 值不同。
如果同時帶有E-tag和Last-Modified,服務端優先檢查E-tag。
⑧ 瀏覽器緩存機制
有dns的地方,就有緩存。瀏覽器、操作系統、Local DNS、根域名伺服器,它們都會對DNS結果做一定程度的緩存。
DNS查詢過程如下:
首先搜索瀏覽器自身的DNS緩存,如果存在,則域名解析到此完成。
如果瀏覽器自身的緩存裡面沒有找到對應的條目,那麼會嘗試讀取操作系統的hosts文件看是否存在對應的映射關系,如果存在,則域名解析到此完成。
如果本地hosts文件不存在映射關系,則查找本地DNS伺服器(ISP伺服器,或者自己手動設置的DNS伺服器),如果存在,域名到此解析完成。
如果本地DNS伺服器還沒找到的話,它就會向根伺服器發出請求,進行遞歸查詢。
瀏覽器本地緩存失效後,瀏覽器會向CDN邊緣節點發起請求。類似瀏覽器緩存,CDN邊緣節點也存在著一套緩存機制。CDN邊緣節點緩存策略因服務商不同而不同,但一般都會遵循http標准協議,通過http響應頭中的
Cache-control: max-age 的欄位來設置CDN邊緣節點數據緩存時間。
當瀏覽器向CDN節點請求數據時,CDN節點會判斷緩存數據是否過期,若緩存數據並沒有過期,則直接將緩存數據返回給客戶端;否則,CDN節點就會向伺服器發出回源請求,從伺服器拉取最新數據,更新本地緩存,並將最新數據返回給客戶端。 CDN服務商一般會提供基於文件後綴、目錄多個維度來指定CDN緩存時間,為用戶提供更精細化的緩存管理。
CDN 優勢
CDN節點解決了跨運營商和跨地域訪問的問題,訪問延時大大降低。
大部分請求在CDN邊緣節點完成,CDN起到了分流作用,減輕了源伺服器的負載。
http請求報文(request)
請求行
請求方法 空格 URL 空格 協議版本 回車符 換行符
請求頭(通用信息頭、請求頭、實體頭)
頭部欄位名 冒號 值 回車鍵 換行符
...
頭部欄位名 冒號 值 回車鍵 換行符
空行
回車符 換行符
實體主體(只有post請求有)
主體
http響應報文(response)
狀態行
協議版本 空格 狀態碼 空格 狀態碼描述 回車符 換行符
響應頭部
頭部欄位名 冒號 值 回車符 換行符
...
頭部欄位名 冒號 值 回車符 換行符
空行
回車符 換行符
響應正文
正文
瀏覽器初次向伺服器發起請求後拿到請求結果,會根據響應報文中HTTP頭的緩存標識,決定是否緩存返回的結果,是則將請求結果和緩存標識存入瀏覽器緩存中
瀏覽器每次發起請求,都會現在瀏覽器緩存中查找該請求的結果以及緩存標識
瀏覽器 瀏覽器緩存 伺服器
——————第一次發起http請求——————>
<——沒有該請求的緩存結果和緩存標識————
——————————————發起http請求——————————————>
<——————————返回該請求結果和緩存規則————————————
——將請求結果和緩存標識存入瀏覽器緩存——>
強制緩存就是向瀏覽器緩存查找結果,並根據該結果的緩存規則來決定是否使用該緩存結果的過程
強制緩存的情況分為三種:
1、不存在該緩存結果和緩存標識,強制緩存失效,直接向伺服器發起請求
2、存在該緩存結果和緩存標識,但結果已經失效,強制緩存失效,使用協商緩存
3、存在該緩存結果和緩存標識,且該結果沒有失效,強制緩存生效,直接返回該結果
控制強制緩存的欄位:Expires,Cache-Control
Expires 是 HTTP/1.0 控制緩存的欄位,值為伺服器返回該請求的結果緩存時間
即再次發送請求是,客戶端時間 小於 Expires的值,直接使用緩存結果
Cache-Control 是HTTP/1.1的規則,主要用於控制網頁緩存,主要取值為:
public:所有的內容都緩存(客戶端和代理伺服器都可以緩存)
private:所有內容只有客戶端可以緩存(默認值)
no-cache:客戶端緩存內容,但是是否使用緩存則需要經過協商緩存來驗證決定
no-store:即不使用強制緩存,也不使用協商緩存
max-age=xxx:緩存內容將在xxx秒後失效
Expires 是一個絕對值
Cache-Control 中 max-age 是相對值,解決了 Expires時期 服務端與客戶端 可能出現時間差的問題
註:Expires和Cache-Control同時存在時,只有Cache-Control生效
協商緩存就是強制緩存失效後,瀏覽器攜帶緩存標識向伺服器發起請求,由伺服器根據緩存標識決定是否使用緩存的過程
協商緩存的兩種情況:
1、協商緩存生效,返回304,繼續使用緩存
過程:
瀏覽器 瀏覽器緩存 伺服器
————————發起http請求————————>
<——該請求的緩存結果失效,只返回緩存標識——
————————攜帶該資源的緩存標識,發起http請求————————>
<—————————————304,該資源無更新————————————
——————獲取該請求的緩存結果——————>
<——————返回該請求的緩存結果——————
2、協商緩存失敗,返回200和請求結果
過程:
瀏覽器 瀏覽器緩存 伺服器
————————發起http請求————————>
<——該請求的緩存結果失效,只返回緩存標識——
————————攜帶該資源的緩存標識,發起http請求————————>
<————————200,資源已更新,重新返回請求和結果———————
——將該請求結果和緩存標識存入瀏覽器緩存中—>
協商緩存的標識也是在響應報文的HTTP頭中和請求結果一起返回給瀏覽器的
控制協商緩存的欄位:
(1) Last-Modified/If-Modified-Since:Last-Modified是伺服器響應請求是,返回該資源文件在伺服器最後被修改的時間;If-Modified-Since再次發起請求時,攜帶上次返回的Last-Modified的值,伺服器將該欄位值與該資源最後修改時間對比,決定是否用緩存
(2)Etag/If-None-Match:Etag伺服器響應請求時,返回當前資源文件的一個唯一標識,由伺服器生成之;If-None-Match是再次發起請求時,攜帶上次返回的唯一標識Etag的值,伺服器收到後,將該欄位值與該資源在伺服器上的Etag對比,一致 則返回304,否則返回200
註:Etag/If-None-Match優先順序高於Last-Modified/If-Modified-Since,同時存在時只有Etag/If-None-Match生效
瀏覽器緩存分為:內存緩存 和 硬碟緩存
內存緩存特性:
(1)快速讀取:內存緩存會將編譯解析後的文件,存入該進程的內存中,便於下次運行時快速讀取
(2)時效性:一旦關閉進程,進程內存清空
硬碟緩存特性:
永久性:直接寫入硬碟文件中
復雜、緩慢:讀取緩存對該緩存存放的硬碟文件進行I/O操作,重新解析
from memory cache:使用內存中的緩存
from disk cache:使用硬碟中的緩存
瀏覽器讀取順序:memory ——> disk
瀏覽器將js和圖片等文件解析執行後直接存入內存緩存中,F5刷新頁面時,from memory cache(使用內存中的緩存)
css文件存入硬碟中,F5刷新頁面時,from disk cache(使用硬碟中的緩存)
參考文章
https://segmentfault.com/a/1190000017962411
https://www.cnblogs.com/chengxs/p/10396066.html
⑨ 瀏覽器中的緩存
在我們使用瀏覽器訪問網頁的過程中,瀏覽器經常會緩存各種網頁中的內容。當再次訪問同一個網頁時,可以發現部分內容是從緩存直接讀取的。
查看HTTP的響應信息,就能發現一些端倪。比如響應 200 from cache; 304 not modify 等等。
下面對瀏覽器使用緩存的各種情形做一下分析:
Pragma是HTTP 1.0版本的一個參數,在HTTP 1.1版本裡面這個參數也會生效,如果不想瀏覽器緩存網頁的內容,可以在 Response header 裡面加上 :Pragma: no-cache。
Cache-Control是HTTP 1.1版本新增的一個參數。
Cache-Control:no-store 不允許緩存
Cache-Control:no-cache 不允許直接使用緩存,需要先發起請求和伺服器協商(這個經常被誤認為是不允許緩存,實際上它的作用是讓瀏覽器在使用緩存前先請求服務端一次,確認內容是否有更新)
這樣的響應代表沒有跟服務端進行交互,內容是直接從本地讀取的。
Expires和Cache-control: max-age= 有類似的作用,都是指定緩存內容的有效周期,Expires指定的格式是格林威治時間,max-age則是秒數。
服務端也可以在 Response header 里加上 Last-Modified,它的格式是格林威治時間,再次請求時,瀏覽器的 Request header 中會多出一個叫 If-Modified-Since的值,通過比較這兩個值是否一致來決定是否返回304。
ETag的用法和 Last-Modified 類似,值是一種文件指紋。比如:ETag:"5a3ccff0-5dc"。
服務端在 Response header 里加上 ETag,再次請求時,瀏覽器的 Request header 中會多出一個叫 If-None-Match的值,通過比較這兩個值是否一致來決定是否返回304。
總體來說,瀏覽器使用緩存時有兩種表現:
1.直接從本地讀取,不與服務端有交互,就是 200 OK (from memory cache)。
2.請求一次服務端,查看本地緩存是否生效,這種方式叫 協商緩存。如果服務端判斷緩存有效,將不返回完整內容,而是返回 304 Not Modified。
在優先順序上 Pragma > Cache-Control > Expires。