1. 程式人生 > >web緩存策略之HTTP緩存大全

web緩存策略之HTTP緩存大全

樂觀鎖 log com 請求報文 相對 文件 客戶端 最新 擁有

一. web緩存總分類

  • 數據庫數據緩存

    Web應用,特別是SNS類型的應用,往往關系比較復雜,數據庫表繁多,如果頻繁進行數據庫查詢,很容易導致數據庫不堪重荷。為了提供查詢的性能,會將查詢後的數據放到內存中進行緩存,下次查詢時,直接從內存緩存直接返回,提供響應效率。比如常用的緩存方案有memcached等。

  • 服務器端緩存

    • 代理服務器緩存

      代理服務器是瀏覽器和源服務器之間的中間務器,瀏覽器先向這個中間服務器發起W eb求,經過處理後(比如權限驗證,緩存匹配),再將請求轉發到源服務器。代理 服務器存的運作原理跟瀏覽器的運作原理差不多,是規模更大。可以把它理解為一 個共享緩存不只為一個用戶服務,一般為大量用戶提供務,因此在減少相應時間和 帶寬使用方面很效,同一個副本會被重用多次。常見代理服器緩存解決方案有Squid 等,這裏不再詳述。

    • CDN緩存-CDN緩存策略

      CDN邊緣節點緩存策略因服務商不同而不同但一般都會遵循http標準協議,通過http 響 應頭中的Cache-control:max-age的字段來設置CDN邊緣節點數據緩存間。

      當客戶端向CDN節點請求數據時,CDN節點會斷緩存數據是否過期,若緩存數據並沒 有 過期,則直接將緩存數據返回給客戶端否則,CDN節點就會向源站發出回 源請求(bak to the sourcerequest),從源站拉取最新數據,更新本緩存,並將最新數據返回給 客戶端。

      CDN服務商一般會提供基於文件後綴、目錄個維度來指定CDN緩存時間,為用戶提供 更 精細化的緩存管理。

      CDN緩存時間會對“回源率”產生直接的影響若CDN緩存時間較短,CDN邊緣節點上的數 據 會經常失效,導致頻繁回源,增加了源站的載,同時也增大的訪問延時;若C DN緩存時 間太長,會帶來數據更新時間慢的問題。發者需要增對特定的業務, 來做特定的數據 緩存時間管理。

      CDN緩存刷新CDN邊緣節點對開發者是透明的相比於瀏覽器Ctrl+F5的強制刷新來使瀏 覽 器本地緩存失效,開發者可以通過CDN務商提供的“刷新緩存”接口來達到清 理CDN邊 節點緩存的目的。這樣開發者在更新數據後可以使用“刷新緩存”功能來強 制CDN節點上 的數據緩存過期,保證客戶端在訪問,拉取到最新的數據。

    • Combo服務

      Combo服務,也就是我們在最終拼接生成頁資源引用的時候,並不是生成多個獨立的 lin標簽,而是將資源地址拼接成一個url路徑請求一種線上的動態資源合並服務, 從而實減少HTTP請求的需求。 /??fle1,file2,file3,...的url請求響應就動態combo服務提供的,它的原理很簡單 , 就是根據url找到對應的多個文件,合成一個文件來響應請求,並將其緩 存,以加訪 問速度。

      但它也存在一些缺陷:

      瀏覽器有url長度限制,因此不能無限制的並資源。 如果用戶在網站內有公共資源的兩個頁面間轉訪問,由於兩個頁面的combo的url不 一 樣導致用戶不能利用瀏覽器緩存來加快公共資源的訪問速度。如果combo的 url中任何 一個文件發生改變,都會導致整個url存失效,從而導致瀏覽器緩存 利用率降低。

  • 瀏覽器端緩存

    瀏覽器緩存根據一套與服務器約定的規則進行工作,在同一個會話過程中會檢查一次並確定緩存的副本足夠新。如果你瀏覽過程中,比如前進或後退,訪問到同一個圖片,這些圖片可以從瀏覽器緩存中調出而即時顯現。

  • Web應用層緩存

    應用層緩存指的是從代碼層面上,通過代碼邏輯和緩存策略,實現對數據,頁面,圖片等資源的緩存,可以根據實際情況選擇將數據存在文件系統或者內存中,減少數據庫查詢或者讀寫瓶頸,提高響應效率。

前端包含瀏覽器端緩存和Web應用層緩存兩部分。

二. http緩存

1. http緩存機制

緩存行為主要由緩存策略決定,而緩存策略由內擁有者設置。這些策略主要通過特定的HTTP頭部清晰地表達。

當一個用戶發起一個靜態資源請求的時候,瀏覽會通過以下幾步來獲取資源:

  • 本地緩存階段:先在本地查找該資源,如果有現該資源,而且該資源還沒有過期,就使用這一資源,完全不會發送http請求到服務器;

  • 協商緩存階段:如果在本地緩存找到對應的資,但是不知道該資源是否過期或者已經過期,則一個http請求到服務器,然後服務器判斷這個請,如果請求的資源在服務器上沒有改動過,則返304,讓瀏覽器使用本地找到的那個資源;

  • 緩存失敗階段:當服務器發現請求的資源已經修改過,或者這是一個新的請求(在本來沒有找到資源),服務器則返回該資源的數據,並且返回200, 當然這個是指找到資源的情況下,如果服務器上沒有這個資源,則返回404。

  • 用戶操作行為與緩存 瀏覽器中的操作對緩存的影響:

    • 強制刷新 – 當按下ctrl+F5來刷新頁面的時候, 瀏覽器將繞過各種緩存(本地緩存和協商緩存), 直接讓服務器返回最新的資源;
    • 普通刷新 – 當按下F5來刷新頁面的時候,瀏覽器將繞過本地緩蹲來發送請求到服務器, 此時, 協商緩存是有效的
    • 回車或轉向 – 當在地址欄上輸入回車或者按下跳轉按鈕的時候, 所有緩存都生效

技術分享圖片

1.1 本地緩存階段(/強制緩存)

  • Expires指定緩存到期GMT的絕對時間,如果設max-age,max-age就會覆蓋expires。如果expire到期需要重新請求。

    Expires是HTTP/1.0控制網頁緩存的字段,其值為服務器返回該請求結果緩存的到期時間,即再次發起該請求時,如果客戶端的時間小於Expires的值時,直接使用緩存結果。

    Expires是HTTP/1.0的字段,但是現在瀏覽器默認使用的是HTTP/1.1,那麽在HTTP/1.1中 網頁緩存還是否由Expires控制?

    到了HTTP/1.1,Expire已經被Cache-Control替代,原因在於Expires控制緩存的原理是 使用客戶端的時間與服務端返回的時間做對比,那麽如果客戶端與服務端的時間因為某 些原因(例如時區不同;客戶端和服務端有一方的時間不準確)發生誤差,那麽強制緩 存則會直接失效,這樣的話強制緩存的存在則毫無意義,那麽Cache-Control又是如何控 制的呢?

  • Cache-Control

    Cache-Control:這個是http 1.1中為了彌補Expires 缺陷新加入的。 對已緩存的內容進行控制:

    • public:表示緩存的版本可以被代理服務器或其他中間服務器識別,所有內容都將被緩 存(客戶端和代理服務器都可緩存)。

    • private: 意味著這個文件對不同的用戶是不的。只有用戶自己的瀏覽器能夠進行緩 存,公共的代理服務器不允許緩,即所有內容只有客戶端可以緩存,Cache-Control的默 認取值。

    • no-cache: 客戶端緩存內容,但是是否使用緩存則需要經過協商緩存來驗證決定意味 著文件的內容不應當被緩存。在搜索或者翻頁結果中非 常有用,因為同樣的URL,對應的內容會發生變化。

    • max-age:指定緩存過期的相對時間秒數,max-ag=0或是負值,瀏覽器會在對應的存 中把Expires設置為1970-01-01 08:00:00 。max-age=xxx (xxx isnumeric):緩存內容將在xxx秒後失效。

    • s-maxage:類似於max-age,只用在共享緩存上,比如prxy.

    • public:通常情況下需要http身份驗證的情況,響應不可cahce的,加上public可使 它被cache。

    • no-cache:強制瀏覽器在使用cache拷貝之前先提交一http請求到源服務器進行確。 這對身份驗證來說是非常有用的,能比較好的遵守 (可以結合public進行考慮)。它對維持一個資源總是最新的也很有用,與此同時不完全 喪失cache帶來的好處),因為它在本地是有拷貝的,但是在用之都進行了確認, 這樣ht tp請求並未減少,但可能會減少一個響應體。

    • no-store:告訴瀏覽器在任何情況下都不要進行cache不在本地保留拷貝。所有內都不 會被緩存,即不使用強制緩存,也不使用協商緩存

    • must-revalidate:強制瀏覽器嚴格遵守你設置的cache規則。

    • proxy-revalidate:強制proxy嚴格遵守你設置的cache規則。

    用法舉例: Cache-Control: max-age=3600,must-revalidate

    cache:使用本地緩存,不發生請求。

1.2 協商緩存階段

  • Last-Modified &if-modified-sinceLast-Modified與If-ModifiedSince是一對報文頭,屬於http 1.0。 last-modified是WEB服務器認為對象的最後改時間,比如文件的最後修改時間,動態頁的最後產生時間。

  • ETag & If-None-MatchETag與If-None-Match一對報文,屬於http 1.1。 ETag可以用來解決這種問題。ETag是一個文的唯一標誌符。就像一個哈希或者指紋,每文件都有一個單獨的標誌,只要這個文件發了改變,這個標誌就會發生變化。 ETag機制類似於樂觀鎖機制,如果請求報文ETag與服務器的不一致,則表示該資源已經修改過來,需要發最新的內容給瀏覽器。 同時使用這兩個報文頭,在完全匹配If-Modiied-Since和If-None-Match即檢查完修改時和Etag之後,如都與服務器的相符,服務器回304,否則,發送最新內容給瀏覽器。 Etag/lastModified過程如下:

    1.客戶端請求一個頁面(A)。

    2.服務器返回頁面A,並在給A加上一個Last-odified/ETag。

    3.客戶端展現該頁面,並將頁面連同Last-Modified/ETag一起緩存。

    4.客戶再次請求頁面A,並將上次請求時服器返回的Last-Modified/ETag一起傳遞給服 務器。

    5.服務器檢查該Last-Modified或ETag,並斷出該頁面自上次客戶端請求之後還未被修 改,直接返回響應304和一個空的響應體。 304:通過If-Modified-Since If-Match判斷資源是否修改,如未修改則返304,發生了一次請求,但請求內容長度為 0,節省了帶寬。如果有多臺負載均衡的服務器,不同服務器算出的可能不同, 這樣就會造成資源的重復加載。

    Etag 主要為了解決 Last-Modified無法解決的一些問題:

    1、一些文件也許會周期性的更改,但是他內容並不改變(僅僅改變的修改時間),這個 時候我們並不希望客戶端認為這個文件被修了,而重新GET;

    2、某些文件修改非常頻繁,比如在秒以下時間內進行修改,(比方說1s內修改了N次) ,If-Modified-Since能檢查到的粒度是s的,這種修改無法判斷(或者說UNIX記錄MTIM E只能精確到秒);

    3、某些服務器不能精確的得到文件的最後改時間。

    其他標簽 Content-Length:盡管並沒有在緩存中明確及,Content-Length頭部在設置緩存策略 時很重要。某些軟件如果不提前獲知內的大小以留出足夠空間,則會拒絕緩存該內容 。

    Vary:緩存系統通常使用請求的主機和路徑為存儲該資源的鍵。當判斷一個請求是否 是請求同樣內容時,Vary頭部可以被用提醒緩存系統需要註意另一個附加頭部。它通 常被用來告訴緩存系統同樣註意Accept-Encding頭部,以便緩存系統能夠區分壓縮和未 壓縮的內容。

1.3 理解瀏覽器的內存和硬盤儲存

  • 內存緩存(from memorycache):內存緩存具有兩個特點,分別是快速讀和時效性:

    • 快速讀取:內存緩存會將編譯解析後的文件,直接存入該進程的內存中,占據該進程一定的內存資源,以方便下次運行使用時的快速讀取。

    • 時效性:一旦該進程關閉,則該進程的內存則會清空。

  • 硬盤緩存(from disk cache):硬盤緩存則是直接將緩存寫入硬盤文件中,讀取緩存需要對該緩存存放的硬盤文件進行I/O操作,然後重新解析該緩存內容,讀取復雜,速度比內存緩存慢。

在瀏覽器中,瀏覽器會在js和圖片等文件解析執行後直接存入內存緩存中,那麽當刷新頁面時只需直接從內存緩存中讀取(from memory cache);而css文件則會存入硬盤文件中,所以每次渲染頁面都需要從硬盤讀取緩存(from disk cache)。

1.4 無法被瀏覽器緩存的請求

  • HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請求
  • 需要根據Cookie,認證信息等決定輸入內容的動態請求是不能被緩存的
  • 經過HTTPS安全加密的請求(有人也經過測試發現,ie其實在頭部加入Cache-Control:max-age信息,firefox在頭部加入Cache-Control:Public之後,能夠對HTTPS的資源進行緩存,參考《HTTPS的七個誤解》)
  • POST請求無法被緩存
  • HTTP響應頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請求無法被緩存

參考文章

https://imweb.io/topic/55c6f9bac222e3af6ce235b9

https://juejin.im/entry/58ba3302570c350062124f68

http://www.alloyteam.com/2012/03/web-cache-3-how-to-build-cacheable-website/

https://imweb.io/topic/5590a443fbb23aae3d5e450a

https://heyingye.github.io/2018/04/16/徹底理解瀏覽器的緩存機制/

web緩存策略之HTTP緩存大全