場景1:測試妹子測功能時會說爲何個人瀏覽器的顯示亂七八糟,個人界面怎麼跟別人瀏覽器上不一致?旁邊的人會提醒說:清下緩存試試。css
場景2:開發改了代碼,上了環境,發現不生效,這時候首先就是清緩存,清了瀏覽器緩存發現仍是不行,再檢查,發現是反向代理緩存。html
那麼,當咱們談WEB緩存的時候,咱們說的是什麼?什麼地方能夠緩存?何時用什麼緩存?使用不當會帶來什麼問題,咱們怎麼避免?前端
會不會傻傻分不清楚,那咱們就來理一理,看看web緩存到底是什麼?html5
緩存:緩存就是把數據或者咱們須要取到的內容,放到能更快訪問的地方。緩存對於前端後端的coder來講,應該都不陌生,不論前端後端,咱們使用緩存都是爲了提高性能。java
Web緩存:按照上面的邏輯,就是爲了提高Web頁面訪問的性能,把能緩存的頁面or數據緩存到可以更快取得的地方。廣義的Web緩存也能夠包括服務器緩存,本文爲了與服務器緩存區分,不包含服務器緩存。nginx
在典型的web應用中,一個瀏覽器發起的請求,會通過下圖中的幾個步驟(其中CDN、反向代理是可選的),那麼緩存的地方或者層次也很好理解,就是下圖中的瀏覽器、反向代理、cdn。web
瀏覽器緩存是全部WEB應用都會使用的,瀏覽器的緩存類型不少,咱們能夠經過瀏覽器提供的開發者工具來查看。chrome
以chrome瀏覽器爲例,打開chrome開發者工具,再選擇「Resources」中看到全部的緩存類型,以下圖所示:數據庫
1、Frames後端
Frames的緩存,是基於HTTP協議的瀏覽器文件級緩存。
瀏覽器在發送文件請求時,能夠根據協議頭判斷從服務器端請求文件仍是從本地緩存讀取文件,主要判斷依據是expires和etag,讀取文件的流程以下圖:
從這張流程圖能夠看出,影響瀏覽器的文件緩存主要有幾個屬性:expires、Etag、Last-Modified,這三個屬性是由http協議定義的。
(一)控制緩存的屬性
在http1.0中約定用expires來肯定是否使用緩存中的文件。http1.1中約定使用的是Cache-Control、Last-Modified/If-Modified-Since、etag。下面來分別看下各類屬性的定義:
一、Expires
用於設置靜態資源的過時時間。
二、Cache-Control
Cache-Control能夠用於控制是否緩存、緩存的讀取權限、資源的有效期。只不過Cache-Control的選擇更多,設置更細緻,若是同時設置的話,其優先級高於Expires。
(1)public 指示響應數據能夠被任何客戶端緩存
(2)private 指示響應數據能夠被非共享緩存所緩存。這代表響應的數據能夠被髮送請求的瀏覽器緩存,而不能被中介所緩存
(3)no-cache 指示響應數據不能被任何接受響應的客戶端所緩存
(4)no-store 指示所傳送的響應數據除了不能被緩存,也不能存入磁盤。通常用於敏感數據,以避免數據被複制。
(5)must-revalidate 指示全部的緩存都必須從新驗證,在這個過程當中,瀏覽器會發送一個If-Modified-Since頭。若是服務器程序驗證得出當前的響應數據爲最新的數 據,那麼服務器應當返回一個304 Not Modified響應給客戶端,不然響應數據將再次被髮送到客戶端。
(6)proxy-revalidate 與must-revalidate類似,不一樣的是用來指示共享緩存。
(7)max-age:(單位秒) 數據通過max-age設置的秒數後就會失效,至關於HTTP/1.0中的Expires頭。若是在一次響應中同時設置了max-age和Expires,那麼max-age將具備較高的優先級。(注:ngnix設置expires會被轉換爲max-age)
三、Last-Modified/If-Modified-Since
l Last-Modified:標示這個響應資源的最後修改時間。web服務器在響應請求時,告訴瀏覽器資源的最後修改時間。
l If-Modified-Since:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Last-Modified聲明,則再次向web服務器請求時帶上頭 If-Modified-Since,表示請求時間。web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對。若最後修改時間較新,說明資源又被改動過,則響應整片資源內容(寫在響應消息包體內),HTTP 200;若最後修改時間較舊,說明資源無新修改,則響應HTTP 304 (無需包體,節省瀏覽),告知瀏覽器繼續使用所保存的cache。
四、Etag/If-None-Match
Etag/If-None-Match也要配合Cache-Control使用。
Etag:web服務器響應請求時,告訴瀏覽器當前資源在服務器的惟一標識(生成規則由服務器定義)。nginx中,etag會默認增長,若是須要關閉,須要在配置文件中設置:etag off;
l If-None-Match:當資源過時時(使用Cache-Control標識的max-age),發現資源具備Etage聲明,則再次向web服務器請求時帶上頭If-None-Match (Etag的值)。web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304。
(二)用戶行爲與緩存
瀏覽器緩存行爲還有用戶的行爲有關
用戶操做 | Expires/Cache-Control | Last-Modified/Etag |
地址欄回車 | 有效 | 有效 |
頁面連接跳轉 | 有效 | 有效 |
新開窗口 | 有效 | 有效 |
前進、後退 | 有效 | 有效 |
F5刷新 | 無效 | 有效 |
Ctrl+F5刷新 | 無效 | 無效 |
(二)如何控制緩存
設置緩存的兩種方式:
一、web服務器配置
以ngnix爲例,在nginx.conf中設置:
location~ .*\.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*) {
expires 1d;
}
上述配置表示這些靜態文件1天后過時。若是想配置爲徹底不緩存,那麼能夠設置爲expires -1;(後面的數字配置爲負數),返回的header會被設置爲Cache-Control:no-cache
二、後臺代碼寫入
例如:
response.setHeader("Cache-Control", "no-cache");
三、html 的meta標籤
<meta http-equiv="Cache-Control" content="max-age=7200" />
(三)緩存的問題和解決辦法
一、引入緩存以後,主要有兩個問題:
(1)瀏覽器不知道有資源更新,仍是使用緩存中的老文件。
(2)各個文件緩存策略不一致,有關聯關係的文件,有的從服務器加載,有的直接取瀏覽器緩存的,這樣有可能會致使界面混亂。
二、解決方式
(1)Etag或Last-modified
Etag是服務端根據文件信息生成的字符串,當服務端文件更新時,Etag也會變化,這樣能保證當服務端文件更新時,取到新的文件內容。
可是Etag這種解決方式的問題是,請求仍是會發到服務端,由服務端進行判斷。
Last-modified與Etag相似。
(2)文件名後綴
構建過程當中,把構建生成的文件加上隨機後綴,主入口html中的引用文件在構建中替換爲增長了文件名後綴的;主入口文件配置爲不緩存。
當服務端更新文件時,因爲文件名後綴更改,瀏覽器緩存匹配不上,會直接到服務端獲取,服務端沒有更新文件時,在瀏覽器緩存獲取。
這種方式效果較好,可是須要引入構建,對於已經使用了前端構建的web應用比較適用。
2、cookie
cookie是一種可以讓網站服務器把少許數據儲存到客戶端的硬盤或內存,或是從客戶端的硬盤讀取數據的一種技術。當咱們瀏覽某網站時,由Web服務器置於你硬盤上的一個很是小的文本文件,它能夠記錄用戶ID、密碼、瀏覽過的網頁、停留的時間等信息。
cookie以鍵值對的方式來存儲,有數量和大小的限制,數量各個瀏覽器不一樣,大小不能超過4K。
(一)設置cookie的方式:
一、瀏覽器
瀏覽器提供了操做cookie的方式,能夠對cookie進行設置、讀取、刪除。另外,cookie也能夠設置過時時間。
瀏覽器獲取cookie的方式:
document.cookie
二、服務器
不少時候,咱們會使用cookie來作協助作會話管理,登陸成功後,由服務端將sessionid信息寫入cookie,後續客戶端發送的全部請求都攜帶cookie信息,服務端驗證cookie中的sessionid信息,判斷此請求是否合法。以java爲例,服務端寫入cookie的方法以下:
Cookie cookie = new Cookie("sessionid",URLEncoder.encode("fejerwiie2234","UTF-8")); response.addCookie(cookie);
(二)cookie的屬性
屬性名稱 | 屬性含義 |
name | cookie的名稱 |
value | cookie的值 |
domain | 能夠訪問此cookie的域名 |
path | 能夠訪問此cookie的頁面路徑。 如domain是abc.com,path是/test,那麼只有/test路徑下的頁面可讀取此cookie |
expires/Max-Age | 字段爲此cookie超時時間。若設置其值爲一個時間,那麼當到達此時間後,此cookie失效。不設置的話默認值是Session,意思是cookie會和session一塊兒失效。當瀏覽器關閉(不是瀏覽器標籤頁,而是整個瀏覽器) 後,此cookie失效 |
Size | 此cookie大小 |
httponly | cookie的httponly屬性。若此屬性爲true,則只有在http請求頭中會帶有此cookie的信息,而不能經過document.cookie來訪問此cookie。 |
secure | 設置是否只能經過https來傳遞此條cookie |
3、localStorage
localstorage是Html5中新加入的特性,引入localstorage主要是做爲瀏覽器本地存儲,解決cookie做爲存儲容量不足的問題。localstorage是一種持久化的存儲。
一樣,localstorage也是一個key-value形式的存儲。
(一)瀏覽器提供了localstorage的增刪改查方法
增長/修改:window.localStorage.setItem("username","admin");
查詢:window.localStorage.getItem("username");
刪除:window.localStorage.removeItem("username","admin");
(二)使用localstorage的注意事項
localstorage中存儲的value只能是字符串型,若是要存儲對象,須要轉換爲字符串再進行保存。
4、sessionStorage
sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問而且當會話結束後數據也隨之銷燬。所以sessionStorage不是一種持久化的本地存儲,僅僅是會話級別的存儲。
一樣,瀏覽器也提供了sessionStorage的增刪改查方法,與localStorage一致,只是獲取方法爲:window.sessionStorage。
5、IndexedDB
IndexedDB也是html5提供的,可以在客戶端存儲大量的結構化數據的數據庫,而且提供API進行高效檢索。IndexedDB的初始大小是50M,還能夠增長,就存儲量來講,秒殺其餘存儲方式。
可是它的缺點也很明顯,IndexedDB並非全部主流瀏覽器都支持,好比IE九、IE10和IE11都不支持,因此,若是你的用戶羣還使用着IE系列的瀏覽器,IndexedDB就不用考慮了。
IndexedDB也有一些api,這裏再也不詳述了,能夠參考:
https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
6、Web SQL
此方案在W3C已經廢棄,再也不維護,替代方案是IndexedDB。
7、application cache
該特性已經從 Web 標準中刪除。
8、Cache Storage
該方案是一個實驗性的方案,並非全部瀏覽器都支持。
CacheStorage是在ServiceWorker的規範中定義的。CacheStorage 能夠保存每一個serverWorker申明的cache對象,cacheStorage有open、match、has、delete、keys五個核心方法,能夠對cache對象的不一樣匹配進行不一樣的響應。
9、Services Worker
service worker提供了不少新的能力,使得web app擁有與native app相同的離線體驗、消息推送體驗。service worker也是一個實驗性的方案,並非全部瀏覽器都支持。
Service worker能夠:
後臺消息傳遞
網絡代理,轉發請求,僞造響應
離線緩存
消息推送
能夠參考:https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
網站的加載速度,除了資源的多少和大小外,很大部分時間是用於網絡傳輸的,而網絡傳輸時間與用戶瀏覽器與資源所在服務器的地理位置直接相關,要提高網站加載速度,一個辦法就是使資源所在服務器與用戶的地理位置儘可能靠近。
CDN:全稱是Content Delivery Network,即內容分發網絡。其基本思路是儘量避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,使內容傳輸的更快、更穩定。CDN包括分佈式存儲、負載均衡、網絡請求的重定向和內容管理4個要件。而其中呢,內容管理和全局的網絡流量管理是CDN的核心所在。CDN確保內容以一種極爲高效的方式爲用戶的請求提供服務,使用戶可就近取得所需內容,解決 Internet網絡擁擠的情況,提升用戶訪問網站的響應速度。
CDN的拓撲圖以下:
1、CDN的緩存機制
CDN邊緣節點緩存策略因服務商不一樣而不一樣,但通常都會遵循http標準協議,經過http響應頭中的Cache-control: max-age的字段來設置CDN邊緣節點數據緩存時間。當客戶端向CDN節點請求數據時,CDN節點會判斷緩存數據是否過時,若緩存數據並無過時,則直接將緩存數據返回給客戶端;不然,CDN節點就會向源站發出回源請求,從源站拉取最新數據,更新本地緩存,並將最新數據返回給客戶端。因此,若是咱們修改了內容,最好加個版本號,讓CDN從新獲取資源,從而減小沒必要要的麻煩。
CDN服務商通常會提供基於文件後綴、目錄多個維度來指定CDN緩存時間,爲用戶提供更精細化的緩存管理。CDN緩存時間會對「回源率」產生直接的影響。若CDN緩存時間較短,CDN邊緣節點上的數據會常常失效,致使頻繁回源,增長了源站的負載,同時也增大的訪問延時;若CDN緩存時間太長,會帶來數據更新時間慢的問題。開發者須要增對特定的業務,來作特定的數據緩存時間管理。
2、CDN的問題
CDN的分流做用不只減小了用戶的訪問延時,也減小了源站的負載。
但其缺點主要是緩存的同步問題:當網站更新時,若是CDN節點上數據沒有及時更新,即使用戶再瀏覽器使用Ctrl +F5的方式使瀏覽器端的緩存失效,也會由於CDN邊緣節點沒有同步最新數據而致使用戶訪問異常。
3、如何解決CDN的問題
CDN的主要問題是因爲緩存同步不及時帶來的,緩存更新有兩種方式:
(一)定製緩存策略
靜態文件在返回時由源服務器控制expires、cache-control等屬性來定義CDN的緩存策略。
(二)源服務器資源更新時,主動刷新CDN緩存
CDN邊緣節點對開發者是透明的,相比於瀏覽器Ctrl+F5的強制刷新來使瀏覽器本地緩存失效,開發者能夠經過CDN服務商提供的「刷新緩存」接口來達到清理CDN邊緣節點緩存的目的。這樣開發者在更新數據後,可使用「刷新緩存」功能來強制CDN節點上的數據緩存過時,保證客戶端在訪問時,拉取到最新的數據。
第四部分、反向代理緩存
反向代理(Reverse Proxy): 這種機制是Web服務器隱藏在代理服務器以後,實現這種機制的服務器稱做反向代理服務器(Reverse Proxy Server)。此時,Web服務器成爲後端服務器,反向代理服務器稱爲前端服務器。
引入反向代理服務器的目的之一就是基於緩存的加速。咱們能夠將內容緩存在反向代理服務器上,全部緩存機制的實現仍然採用HTTP/1.1協議。
(一)反向代理緩存配置
以一般使用的反向代理--ngnix爲例,實現緩存的配置以下:
一、proxy_cache_path
語法:proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];
默認值:None
使用字段:http
指令指定緩存的路徑和一些其餘參數,緩存的數據存儲在文件中,而且使用代理url的哈希值做爲關鍵字與文件名。levels參數指定緩存的子目錄數,例如:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
文件名相似於:
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
levels指定目錄結構,可使用任意的1位或2位數字做爲目錄結構,如 X, X:X,或X:X:X 例如: 「2」, 「2:2」, 「1:1:2「,可是最多隻能是三級目錄。
二、proxy_cache
語法:proxy_cache zone_name;
默認值:None
使用字段:http, server, location
設置一個緩存區域的名稱,一個相同的區域能夠在不一樣的地方使用。
三、proxy_cache_valid
語法:proxy_cache_valid reply_code [reply_code …] time;
默認值:None
使用字段:http, server, location
爲不一樣的應答設置不一樣的緩存時間,例如:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
爲應答代碼爲200和302的設置緩存時間爲10分鐘,404代碼緩存1分鐘。
若是隻定義時間:
proxy_cache_valid 5m;
那麼只對代碼爲200, 301和302的應答進行緩存。
一樣可使用any參數任何應答。
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
參考地址不明