Web快取詳解(一)

2021-09-12 13:24:20 字數 3877 閱讀 4877

1.請求更快:通過將內容快取在本地瀏覽器或距離最近的快取伺服器(如cdn),在不影響**互動的前提下可以大大加快**載入速度。

2.節省頻寬:對於已快取的檔案,可以減少請求頻寬甚至無需請求網路。

3.降低伺服器壓力:在大量使用者併發請求的情況下,伺服器的效能受到限制,此時將一些靜態資源放置在網路的多個節點,可以起到均衡負載的作用,降低伺服器的壓力。

4.節省使用者的重複性操作,提高使用者體驗。(比如:儲存證件號、姓名或者通過localstorage禁止廣告重複顯示,這樣也節省了寬頻)

web 快取大致可以分為:資料庫快取、伺服器端快取(**伺服器快取、cdn 快取)、瀏覽器快取。我們常說的快取一般指瀏覽器快取。

瀏覽器快取也包含很多內容: memory cache、disk cache(也叫:http cache)、service worker、indexdb、cookie、localstorage、sessionstorage 等。這裡我們一一會進行介紹。

我們可以在 chrome 的開發者工具中,network -> size 一列看到乙個請求最終的處理方式:如果是大小 (多少 k, 多少 m 等) 就表示是網路請求,否則會列出 from memory cache, from disk cache 和 from serviceworker。

它們的優先順序是:(由上到下尋找,找到即返回;找不到則繼續)

·service worker

·memory cache

·disk cache

·網路請求

memory cache

memory cache 是記憶體中的快取,(與之相對 disk cache 就是硬碟上的快取)。按照作業系統的常理:先讀記憶體,再讀硬碟。disk cache 將在後面介紹 (因為它的優先順序更低一些),這裡先討論 memory cache。

幾乎所有的網路請求資源都會被瀏覽器自動加入到 memory cache 中。但是也正因為數量很大但是瀏覽器占用的記憶體不能無限擴大這樣兩個因素,memory cache 注定只能是個「短期儲存」。常規情況下,瀏覽器的 tab 關閉後該次瀏覽的 memory cache 便告失效 (為了給其他 tab 騰出位置)。而如果極端情況下 (例如乙個頁面的快取就占用了超級多的記憶體),那可能在 tab 沒關閉之前,排在前面的快取就已經失效了。

剛才提過,幾乎所有的請求資源 都能進入 memory cache,這裡細分一下主要有兩塊:

1.preloader。

熟悉瀏覽器處理流程的同學們應該了解,在瀏覽器開啟網頁的過程中,會先請求 html 然後解析。之後如果瀏覽器發現了 js, css 等需要解析和執行的資源時,它會使用 cpu 資源對它們進行解析和執行。大約 2007 年以前,「請求 js/css - 解析執行 - 請求下乙個 js/css - 解析執行下乙個 js/css」 這樣的「序列」操作模式在每次開啟頁面之前進行著。很明顯在解析執行的時候,網路請求是空閒的,這就有了發揮的空間:我們能不能一邊解析執行 js/css,一邊去請求下乙個(或下一批)資源呢?

2.preload

preload (雖然看上去和剛才的 preloader 就差了倆字母)。實際上這個大家應該更加熟悉一些,例如 。這些顯式指定的預載入資源,也會被放入 memory cache 中。

memory cache小總結:memory cache 機制保證了乙個頁面中如果有兩個相同的請求 (例如兩個 src 相同的 ,兩個 href 相同的 )都實際只會被請求最多一次,避免浪費。

不過在匹配快取時,除了匹配完全相同的 url 之外,還會比對他們的型別,cors 中的網域名稱規則等。因此乙個作為指令碼 (script) 型別被快取的資源是不能用在 (image) 型別的請求中的,即便他們 src 相等。

在從 memory cache 獲取快取內容時,瀏覽器會忽視例如 max-age=0, no-cache 等頭部配置。例如頁面上存在幾個相同 src 的,即便它們可能被設定為不快取,但依然會從 memory cache 中讀取。這是因為 memory cache 只是短期使用,大部分情況生命週期只有一次瀏覽而已。而 max-age=0 在語義上普遍被解讀為「不要在下次瀏覽時使用」,所以和 memory cache 並不衝突。

但如果站長是真心不想讓乙個資源進入快取,就連短期也不行,那就需要使用 no-store。存在這個頭部配置的話,即便是 memory cache 也不會儲存,自然也不會從中讀取了。(後面的第二個示例有關於這點的體現)

補充:no-store

瀏覽器設定快取的時候,可以用html meta標籤控制快取(非http協議定義)

上述**的作用是告訴瀏覽器當前頁面不被快取,每次訪問都需要去伺服器拉取。這種方法使用上很簡單,但只有部分瀏覽器可以支援,而且所有快取**伺服器都不支援,因為**伺服器不解析html內容本身。

所以,一般應用廣泛的是用 http 頭資訊控制快取。http頭資訊控制快取是通過expires(強快取)、cache-control(強快取)、last-modified/if-modified-since(協商快取)、etag/if-none-match(協商快取)實現。

disk cache

disk cache 也叫 http cache,顧名思義是儲存在硬碟上的快取,因此它是持久儲存的,是實際存在於檔案系統中的。而且它允許相同的資源在跨會話,甚至跨站點的情況下使用,例如兩個站點都使用了同一張。

disk cache 會嚴格根據 http 頭資訊中的各類欄位來判定哪些資源可以快取,哪些資源不可以快取;哪些資源是仍然可用的,哪些資源是過時需要重新請求的。當命中快取之後,瀏覽器會從硬碟中讀取資源,雖然比起從記憶體中讀取慢了一些,但比起網路請求還是快了不少的。絕大部分的快取都來自 disk cache。

凡是永續性儲存都會面臨容量增長的問題,disk cache 也不例外。在瀏覽器自動清理時,會有神秘的演算法去把「最老的」或者「最可能過時的」資源刪除,因此是乙個乙個刪除的。不過每個瀏覽器識別「最老的」和「最可能過時的」資源的演算法不盡相同,可能也是它們差異性的體現。

關於 http 的協議頭中的快取字段,我們會在稍後進行詳細討論。

service worker

上述的快取策略以及快取/讀取/失效的動作都是由瀏覽器內部判斷和進行的,我們只能設定響應頭的某些欄位來告訴瀏覽器,而不能自己操作。舉個生活中去銀行存/取錢的例子來說,你只能告訴銀行職員,我要存/取多少錢,然後把由他們會經過一系列的記錄和手續之後,把錢放到金庫中去,或者從金庫中取出錢來交給你。

但 service worker 的出現,給予了我們另外一種更加靈活,更加直接的操作方式。依然以存/取錢為例,我們現在可以繞開銀行職員,自己走到金庫前(當然是有別於上述金庫的乙個單獨的小金庫),自己把錢放進去或者取出來。因此我們可以選擇放哪些錢(快取哪些檔案),什麼情況把錢取出來(路由匹配規則),取哪些錢出來(快取匹配並返回)。當然現實中銀行沒有給我們開放這樣的服務。

如果 service worker 沒能命中快取,一般情況會使用 fetch() 方法繼續獲取資源。這時候,瀏覽器就去 memory cache 或者 disk cache 進行下一次找快取的工作了。注意:經過 service worker 的 fetch() 方法獲取的資源,即便它並沒有命中 service worker 快取,甚至實際走了網路請求,也會標註為 from serviceworker。這個情況在後面的第三個示例中有所體現。

請求網路

如果乙個請求在上述 3 個位置都沒有找到快取,那麼瀏覽器會正式傳送網路請求去獲取內容。之後容易想到,為了提公升之後請求的快取命中率,自然要把這個資源新增到快取中去。具體來說:

· 根據 service worker 中的 handler 決定是否存入 cache storage (額外的快取位置)。

· 根據 http 頭部的相關字段(cache-control, pragma 等)決定是否存入 disk cache

·memory cache 儲存乙份資源 的引用,以備下次使用。

web窗體快取

在做許可權管理時,出現了模式窗體快取的現象,就是用管理員身份登陸,後訪問奇數次模式窗體,再用另外乙個身份 沒有該模式窗體的訪問許可權 登入後訪問該模式窗體,竟然可以訪問,查明原因之後,明白了原來是,本次訪問的是快取中的資料,這為應用程式,帶來了極大的不安全因素 所以必須解決快取問題,禁止快取 立即過...

web快取技術

php本身沒有所謂處理快取的函式,因為快取實現的方式很多種.如檔案快取,那麼就是操作檔案的相關函式,如memcached,php也有相關的擴充套件函式支援.快取如何使用取決於你的程式快取方式和內容 ob 系列函式是處理向瀏覽器傳送資料的快取,跟資料快取是兩碼事 如果你不使用ob start 那麼你輸...

web快取簡介

1.把內容快取到磁碟上 1 某些框架模板的頁面快取功能,例如smarty,zend framework 快取等等 這些的缺點是你必須用到這些框架或是模板,這也會帶來一些效能的開銷。其實也可以自己寫個簡單的快取方法。2 直接將變化不是很頻繁的內容靜態化,定期更新,靜態檔案的請求速度和消耗資源都遠小於動...