http緩衝知多少,http緩衝知
很久沒有寫部落格了,趁現在也快過年,最近項目不是很忙,寫一篇部落格做為2018年的開始,重拾剛畢業的幾年前寫部落格的衝動。http協議是每個程式猿應該需要知道的東西,不管是前端人員還是後端人員,以前在上家公司的時候,因為項目的需要,曾經專門去瞭解過cdn,其中就需要掌握http協議中的緩衝相關知識。
http緩衝流程圖
直接,後文會具體的敘述
http協議
在介紹http緩衝之前,作為知識鋪墊,先簡單介紹下http報文。http報文就是用戶端(如瀏覽器)和web伺服器通訊時發送和響應的的資料。
http請求由三部分組成分別是請求行、訊息前序、請求本文
http 響應也是由三個部分組成,分別是:狀態行、訊息前序、響應本文
與緩衝相關的資訊,都包含在訊息前序(header)中。不瞭解http協議的,先補充下http協議的知識,google搜尋一大堆,本文就直接略過了。http回應標頭中相關緩衝欄位
隨便請求一個網頁,這裡我們開啟百度首頁,開啟瀏覽器的調試工具
Expires
Expires的值為web伺服器返回的到期時間(GMT 格林威治時間),瀏覽器下次請求時間小於伺服器返回的時間則瀏覽器直接從緩衝中擷取資料,而不用再次發送請求。
Cache-Control
Cache-Control常見的取值有private、public、no-cache、max-age,no-store
private:用戶端可以緩衝
public :用戶端和Proxy 伺服器都可緩衝
max-age=<seconds>:緩衝儲存的最大周期,超過這個時間緩衝被認為到期(單位秒)
no-cache:這個很容易讓人產生誤解,使人誤以為是響應不被緩衝,實際上Cache-Control:no-cache是會被緩衝的,
只不過每次在向瀏覽器提供響應資料時,瀏覽器每次都要向伺服器發送請求,由伺服器來決策來評估緩衝的有效性
no-store: 所有內容都不緩衝(真真的不緩衝)
更多詳細的Cache-Control的取值參考MDN文檔https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
強制緩衝:Expires和Cache-Control區別
Expires和Cache-control稱為強制緩衝,都是在緩衝未失效時,瀏覽器不向服務端發起請求,直接從緩衝中取資料。也許你會有疑問,都是一樣的作用,為什麼要兩個都存在呢?
Expires是上古時代Http1.0的東西了,現在預設瀏覽器均預設使用的是Http1.1了,所以它的作用是可以基本忽略。Expires有一個缺點,就是返回的時間的伺服器的絕對時間,用本地時間和服務端時間比較是否到期,是不嚴謹的,使用者是可以隨便修改本地時間的,那這樣緩衝隨時可以到期,所以被Cache-Control:max-age=<seconds>取代了,在http1.1中Cache-Control優先順序高於Expires。軟體工程的特點是向下相容,Expires一直就沒有拋棄,對於使用http1.0協議的瀏覽器仍然有作用。
Last-Modified
伺服器響應瀏覽器請求,告訴瀏覽器資源的最後修改時間
Etag
伺服器響應請求時,告訴用戶端(瀏覽器)當前請求的資源在伺服器標識(Etag的產生演算法由伺服器決定,不同的web伺服器產生etag的演算法可能還不一樣,Http協議並沒有要求etag的建置規則,如檔案小的時候可以使用md5sum sha1sum,或者根據檔案修改時間,檔案大小,檔案inode檔案屬性綜合產生,這裡不做詳細敘述),我們可以將其理解為一個資源的唯一標識,只要檔案發生變化Etag的值也變化。
對比緩衝:Last-Modified/
If-Modified-Since和Etag/
If-None-Match
Last-Modified和Etag稱為對比緩衝,所謂對比緩衝,顧明思議,就是需要伺服器來比較判斷,來告訴用戶端(瀏覽器)是否可以使用本機快取,對比緩衝生效時,伺服器返回給用戶端(瀏覽器)的Http Code為304,伺服器只是返回的http header資訊,並無響應本文,用戶端通過伺服器返回的狀態代碼304,知道本機快取並無修改,可以直接使用本機快取,這樣大大的較少的用戶端請求回應時間。
對比緩衝大致流程是這樣的,當瀏覽器請求伺服器的某資源時, 伺服器得到資源的最後修改時間(Last-Modified)或根據一定的演算法產生資源的標識(Etag),並將Last-Modified或If-Modified-Since返回給瀏覽器,瀏覽器把Last-Modified或Etag 和 資源內容同時緩衝在本地,當下次再次向伺服器請求此資源時,會將If-Modified-Since: Mon, 07 Nov 2016 07:51:11 GMT 或If-None-Match: xxxxxxx"的要求標頭把發送給伺服器,伺服器再次計算資源的Last-Modified或Etag,如果和用戶端傳來的值比較不相同,則表名資源發生了變化,則給瀏覽器返回Http Code 200。並將資源內容返回給瀏覽器,如果相同表示沒有變化就給瀏覽器返回Http Code 304 ,並不需要返回資源內容給瀏覽器。
對於瀏覽器來說的話,一般會在強制緩衝到期的情況下(或者按F5重新整理,不同的瀏覽器可能不一樣,firefox是按F5)請求資源是,如果資源原先的響應header中帶有Last-Modified和Etag的話,瀏覽器請求時會在請求header中帶上If-Modified-Since和If-None-Match。
Last-Modified和Etag區別
在這裡,也許你可能會問,通過Last-Modified就可以知道資源內容是否發生了變化,為什麼還需要Etag呢,這不是多此一舉嗎?,主要原因Etag解決了Last-modified沒能解決的問題,Etag比Last-Modified更加嚴謹。
1.一些檔案也許會周期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望用戶端認為這個檔案被修改了
2.某些檔案修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷
3.如需要對動態產生的內容做緩衝,那就可以用etag來控制緩衝了
需要注意的是,如果同時有Last-Modified和Etag存在,在發送請求時,瀏覽器會一次性的將這兩個值都發給伺服器,沒有優先順序,伺服器是都比較,還是只比較一個,不同的web伺服器可能比較邏輯不一樣吧。具體的不深究了。
Http要求標頭中Cache-Control: no-cache的意義
一般按ctrl+f5強制重新整理時,要求標頭裡面都帶有Cache-Control: no-cache,其實這是跳過本地的強制緩衝和告訴伺服器跳過對比緩衝,也就是重新請求資源了。對於前端同學在通過GET請求後端API介面時,在ajax的要求標頭中統一帶上Cache-Control: no-cache。
總結
1. 對於強制緩衝,伺服器通知瀏覽器一個緩衝時間,在緩衝時間內,下次請求,直接用緩衝,不在時間內,執行對比緩衝策略。
2. 對於對比緩衝,將緩衝資訊中的Etag和Last-Modified通過請求發送給伺服器,由伺服器校正,返回304狀態代碼時,瀏覽器直接使用緩衝。