我們經(jīng)常會訪問網(wǎng)站,當(dāng)打開一個(gè)陌生的網(wǎng)站時(shí)會發(fā)現(xiàn),打開這個(gè)網(wǎng)站很慢,但打開一個(gè)之前打開過的網(wǎng)站,會發(fā)現(xiàn)很快,這個(gè)是為什么呢?這里就有HTTP緩存機(jī)制。 當(dāng)然網(wǎng)站的訪問快慢,與網(wǎng)站服務(wù)器托管在什么地方有很大關(guān)系,比如中國用戶訪問中國的托管服務(wù)器或云服務(wù)器,肯定會快,訪問海外的會慢。今天說的先假定與網(wǎng)絡(luò)無關(guān),我們一起來聊聊HTTP緩存。 什么是HTTP緩存? HTTP緩存可以說是HTTP性能優(yōu)化中簡單高效的一種優(yōu)化方式了,緩存是一種保存資源副本并在下次請求時(shí)直接使用該副本的技術(shù),當(dāng)web緩存發(fā)現(xiàn)請求的資源已經(jīng)被存儲,它會攔截請求,返回該資源的拷貝,而不會去源服務(wù)器重新下載。 一個(gè)優(yōu)秀的緩存策略可以縮短網(wǎng)頁請求資源的距離,減少延遲,節(jié)省網(wǎng)絡(luò)流量,并且由于緩存文件可以重復(fù)利用,降低網(wǎng)絡(luò)負(fù)荷,提高客戶端響應(yīng)。 因此,學(xué)會利用HTTP緩存是很有必要的。 緩存策略 在闡述HTTP不同緩存策略之前,我們需要知道用戶刷新/訪問行為的手段分成三類: 1,在URI輸入欄中輸入然后回車/通過書簽訪問 2,F(xiàn)5/點(diǎn)擊工具欄中的刷新按鈕/右鍵菜單重新加載 3,Ctl+F5 (完全不使用HTTP緩存) 不同的刷新手段,會導(dǎo)致瀏覽器使用不同的緩存策略。 HTTP緩存主要是通過請求和響應(yīng)報(bào)文頭中的對應(yīng)Header信息,來控制緩存的策略。 響應(yīng)頭中相關(guān)字段為Expires、Cache-Control、Last-Modified、Etag。 HTTP緩存的類型很多,根據(jù)是否需要重新向服務(wù)器發(fā)起請求來分類包括兩種: 強(qiáng)制緩存和對比緩存。 對于強(qiáng)制緩存來說,響應(yīng)header中會有兩個(gè)字段來標(biāo)明失效規(guī)則(Expires/Cache-Control): Expires: Expires 是 HTTP1.0的產(chǎn)物了,現(xiàn)在默認(rèn)瀏覽器均默認(rèn)使用 HTTP1.1,所以它的作用基本忽略。但是很多網(wǎng)站還是對它做了兼容。它的 值為服務(wù)端返回的到期時(shí)間,即下一次請求時(shí),請求時(shí)間小于服務(wù)端返回的到期時(shí)間,直接使用緩存數(shù)據(jù)。 但有一個(gè)問題是到期時(shí)間是由服務(wù)端生成的,如果客戶端時(shí)間跟服務(wù)器時(shí)間不一致,這就會導(dǎo)致緩存命中的誤差。 在HTTP1.1 的版本,Expires 被 Cache-Control替代。 Cache-Control: Cache-Control是最重要的規(guī)則。常見的取值有private、public、no-cache、max-age,no-store,默認(rèn)為 private。 1) max-age:用來設(shè)置資源(representations)可以被緩存多長時(shí)間,單位為 秒; 2) s-maxage:和 max-age 是一樣的,不過它只針對代理服務(wù)器緩存而言; 3) public:指示響應(yīng)可被任何緩存區(qū)緩存; 4) private:只能針對個(gè)人用戶,而不能被代理服務(wù)器緩存; 5) no-cache:強(qiáng)制客戶端直接向服務(wù)器發(fā)送請求,也就是說每次請求都必須向服務(wù)器發(fā)送。服務(wù)器接收到請求,然后判斷資源是否變更,否則返回新內(nèi)容,否則返回304,未變更。這個(gè)很容易讓人產(chǎn)生誤解,使人誤以為是響應(yīng)不被緩存。實(shí)際上Cache-Control: no-cache是會被緩存的,只不過二手游戲賬號買號平臺每次在向客戶端(瀏覽器)提供響應(yīng)數(shù)據(jù)時(shí),緩存都要向服務(wù)器評估緩存響應(yīng)的有效性。 6) no-store:禁止一切緩存(這個(gè)才是響應(yīng)不被緩存的意思)。 舉個(gè)例子,比如一個(gè)資源響應(yīng)頭是: cache-control: public, max-age=31536000 那么這個(gè)資源會被緩存31536000秒(365天),在365天內(nèi)再次請求這條數(shù)據(jù),都會直接獲取緩存數(shù)據(jù)庫中的數(shù)據(jù),直接使用。 那么我們試試再次訪問資源,可以看到HTTP狀態(tài)碼是200,Size這個(gè)字段顯示:disk cache,說明瀏覽器確實(shí)走了強(qiáng)制緩存,沒有再跟瀏覽器交互。 我們上面說了,不同的訪問/刷新手段,會使瀏覽器使用不同的緩存策略,要讓瀏覽器走強(qiáng)制緩存對請求方式有一個(gè)要求: 在URI輸入欄中輸入然后回車/通過書簽訪問。 對比緩存 對比緩存,需要進(jìn)行比較判斷是否可以使用緩存。 瀏覽器第一次請求數(shù)據(jù)時(shí),服務(wù)器會將緩存標(biāo)識與數(shù)據(jù)一起返回給瀏覽器,瀏覽器將二者備份至緩存數(shù)據(jù)庫中。 當(dāng)瀏覽器再次請求數(shù)據(jù)時(shí),瀏覽器將備份的緩存標(biāo)識發(fā)送給服務(wù)器,服務(wù)器根據(jù)緩存標(biāo)識進(jìn)行判斷,判斷成功后,返回304狀態(tài)碼,通知客戶端比較成功,可以使用緩存數(shù)據(jù)。 對于對比緩存來說,響應(yīng)header中會有兩個(gè)字段來標(biāo)明規(guī)則 Last-Modified / If-Modified-Since 服務(wù)器響應(yīng)請求時(shí),會告訴瀏覽器一個(gè)告訴瀏覽器資源的最后修改時(shí)間:Last-Modified,瀏覽器之后再請求的時(shí)候,會帶上一個(gè)頭:If-Modified-Since,這個(gè)值就是服務(wù)器上一次給的Last-Modified的時(shí)間,服務(wù)器會比對資源當(dāng)前最后的修改時(shí)間,如果大于If-Modified-Since,則說明資源修改過了,瀏覽器不能再使用緩存,否則瀏覽器可以繼續(xù)使用緩存,并返回304狀態(tài)碼。 Etag/If-None-Match(優(yōu)先級高于Last-Modified / If-Modified-Since) 服務(wù)器響應(yīng)請求時(shí),通過Etag頭部告訴瀏覽器當(dāng)前資源在服務(wù)器的唯一標(biāo)識(生成規(guī)則由服務(wù)器決定),瀏覽器再次請求時(shí),就會帶上一個(gè)頭If-None-Match,這個(gè)值就是服務(wù)器上一次給的Etag的值,服務(wù)器比對一下資源當(dāng)前的Etag是否跟If-None-Match一致,不一致則說明資源修改過了,瀏覽器不能再使用緩存,否則瀏覽器可以繼續(xù)使用緩存,并返回304狀態(tài)碼。 總之,HTTP緩存主要分強(qiáng)制緩存和對比緩存。 強(qiáng)制緩存的HTTP相關(guān)頭部Cache-Control,Exipres(HTTP1.0),瀏覽器直接讀本地緩存,不會再跟服務(wù)器端交互,狀態(tài)碼200。 對比緩存的HTTP相關(guān)頭部Last-Modified / If-Modified-Since, Etag / If-None-Match (優(yōu)先級比Last-Modified / If-Modified-Since高),每次請求需要讓服務(wù)器判斷一下資源是否更新過,從而決定瀏覽器是否使用緩存,如果是,則返回304,否則重新完整響應(yīng)。 |
|