緩存是一種保存資源副本並在下次請求時直接使用該副本的技術。當 web 緩存發現請求的資源已經被存儲,它會攔截請求,返回該資源的拷貝。html
Web應用緩存技術大致上能夠分爲兩類:服務端緩存和客戶端緩存。兩種目標都是減小重複性內容的生成和網絡傳輸工做,由於緩存數據存儲的位置不一樣,而分爲服務端緩存和客戶端緩存。web
服務端緩存技術關注於服務端數據查詢,生成或者操做技術。主要就是減小處理請求的工做量,減小數據庫查詢次數和生成HTML數據的CPU週期--減小每一個bit的數據。
對於服務端緩存來講,不論是刷新頁面,從新輸入地址,仍是Control+F5都不會規避緩存,若是緩存數據有效,必定是請求的緩存數據。數據庫
輸出緩存是Asp.Net下最經常使用的緩存機制。輸出緩存,緩存服務端生成的HTML數據--緩存Action下返回數據(Html/Json)。這樣,在每次調用相同的Action時,就不須要再次執行Action方法。編程
OutputCache
使緩存的內容通常放在三個位置上:服務端,代理服務器,瀏覽器客戶端。經過Loaction
屬性能夠設置緩存的位置。瀏覽器
Loaction
屬性有以下值:緩存
默認值爲Any
,就是在三個位置都會緩存。可是應該根據不一樣的狀況使用不一樣的緩存位置。好比:要緩存的內容是針對特定用戶的,每一個用戶都會不一樣。這樣的話,該緩存就不能保存在服務器上。應該保存在瀏覽器客戶端上。服務器
在Controller
或者Action
上添加[OutputCache]
特性,使得被添加的Controller
或Action
能夠緩存返回的數據。(在Action
添加會緩存當前的Action
,在Controller
會緩存該Controller
下的全部Action
)網絡
以下代碼:當第一次方法該Action時,開始計時10秒,此10秒內全部訪問該Action的請求都會請求緩存數據。當10秒結束後,再從新開始等待新一次請求,開始新的10秒緩存。就是每隔10秒丟掉舊緩存,等待新的請求,更新緩存數據。mvc
using System.Web.Mvc; using System.Web.UI; namespace MvcApplication1.Controllers { public class HomeController : Controller { //緩存時間10秒,緩存變量爲無,緩存位置爲服務端 [OutputCache(Duration=10, VaryByParam="none", Location = OutputCacheLocation.Server)] public ActionResult Index() { return View(); } } }
View:asp.net
@{ ViewBag.Title = "Index"; } <h2>Index</h2> <p>@DateTime.Now.ToString()</p>
點擊F12,查看請求
須要注意的是:
除了服務端緩存外,客戶端也能夠緩存數據。它避免了向服務器重複提交獲取重複數據的請求,把一些重複數據緩存到本地。服務端緩存是爲了更快的處理客戶端請求,而客戶端緩存則是爲了不沒必要要的請求。
(瀏覽器會自動把靜態資源緩存到瀏覽器)
MVC中指定Location
值爲OutputCacheLocation.Client
使緩存在瀏覽器客戶端上。
using System.Web.Mvc; using System.Web.UI; namespace MvcApplication1.Controllers { public class BadUserController : Controller { //緩存時間爲10秒,緩存參數爲無,緩存位置爲客戶端 [OutputCache(Duration = 10, VaryByParam = "none",Location = OutputCacheLocation.Client)] public ActionResult ClientCache() { return View(); } } }
@{ ViewBag.Title = "ClientCache"; } <h2>ClientCache</h2> <p>@DateTime.Now.ToString()</p>
刷新,從新輸入地址,和Control+F5都有可能破壞客戶端緩存,從服務端從新獲取數據。 瀏覽器刷新,和從新輸入地址會避免請求該URL頁面的客戶端緩存,只避免請求該URL頁面的緩存。(若是該頁面有其餘URL是被客戶端緩存的,這些資源或頁面的緩存不會被避免)。
經過URL訪問,客戶端緩存纔有效。
(頁面的靜態資源)
好比:
304
只有當客戶端和服務端同時都緩存了數據。且緩存沒有更新的時候,纔會有304。即這個緩存是要到服務端驗證(根據ETag和If-Modify-Since),該緩存是否最新。若是要更新緩存,從服務端獲取數據,status code:200,不然status code:304.
304 和200(from cache)區別
304是會到服務端去校驗一次當前客戶端緩存是否有效(根據ETag和If-Modify-Since)。而200(from cache)則沒有向服務端校驗,也沒有向服務端請求,直接使用了客戶端緩存。
有時咱們又須要避免這種沒有向服務端請求,直接使用緩存的狀況。解決辦法就是更改這個緩存的url,添加一個版本號或惟一值。這樣由於url的更改使得在客戶端沒有對應的url緩存,就會從服務端從新獲取,再緩存該URL的數據。
以前的緩存都是Action返回相同的內容。若是Action每次返回的內容不一樣,那又該怎麼緩存這些不一樣的內容呢?
使用OutputCache
特性的VaryByParam
屬性來解決這個問題。當表單參數或查詢字符串參數變化時,該屬性可以建立同一個Action下不一樣的緩存。
以下代碼:Master 獲取列表。Details 獲取列表中選擇項的詳細內容。經過使用VaryByParam
來緩存不一樣的id
的列表項的詳細內容。
using System.Web.Mvc; namespace MvcApplication1.Controllers { public class MoviesController : Controller { public MoviesController() { } [OutputCache(Duration=int.MaxValue, VaryByParam="none")] public ActionResult Master() { //獲取列表 return View(); } [OutputCache(Duration = int.MaxValue, VaryByParam = "id")] public ActionResult Details(int id) { //根據參數id,從數據庫中獲取指定詳細內容,並緩存該內容。不一樣的id會獲得不一樣的內容,天然也會有緩存。 //可是若是設置VaryByParam="none"那麼無論id是多少,都直接從緩存中獲取數據,不執行該Action,這樣就會只返回第一次選擇項的數據。 return View(); } } }
Details()
操做包括一個帶有值「Id」的VaryByParam
屬性。當將Id參數的不一樣值傳遞給控制器操做時,將生成不一樣的緩存內容。
VaryByParam
能夠根據參數緩存不一樣的內容
VaryByParam="*"
: 每當表單或查詢字符串參數變化時,建立一個不一樣的緩存版本。VaryByParam="none"
: 不建立不一樣的緩存內容,不根據參數緩存不一樣的內容,即只有一個內容的緩存。VaryByParam="參數列表"
: 爲不一樣的參數建立不一樣的緩存版本。除了在OutputCache
特性上直接配置緩存策略,能夠在web.config
文件中使用緩存配置文件,同一管理緩存的策略。使用配置文件相比直接使用屬性有以下幾點好處:
能夠實現一次定義,多處使用。
能夠修改web配置文件,而無需從新編譯應用程序。(若是想把已經部署到生產環境中的應用程序禁用緩存,能夠修改web配置文件中定義的緩存配置。對web配置文件的任何更改都將被自動檢測並應用。)
例如,web.config部分定義了一個名爲「cache1Hour」的緩存配置文件。使用該配置項時,只需指定CacheProfile=配置項名稱便可。
<caching> <outputCacheSettings> <outputCacheProfiles> <add name="Cache1Hour" duration="3600" varyByParam="none"/> </outputCacheProfiles> </outputCacheSettings> </caching>
using System; using System.Web.Mvc; namespace MvcApplication1.Controllers { public class ProfileController : Controller { //配置文件中的緩存策略名稱賦值給CacheProfile [OutputCache(CacheProfile="Cache1Hour")] public string Index() { return DateTime.Now.ToString(); } } }
簡單介紹下Http緩存的頭相關信息:
消息頭 | 值 | 類型 | 說明 |
---|---|---|---|
Expires | Thu, 30 Nov 2017 08:21:14 GMT | 響應 | 過時時間,爲格林威治時間 (GMT) |
Pragma | no-cache | 響應 | 忽略瀏覽器緩存(Http1.1用Cache-Control代替) |
Cache-Control | no-cache | 請求/響應 | 客戶端緩存驗證 |
Cache-Control | no-store | 請求/響應 | 不在任何地方保存數據,不容許被緩存 |
Cache-Control | max-age=[秒] | 請求/響應 | 設置瀏覽器緩存最長時間 |
Cache-Control | public | 響應 | 緩存在任何地方 |
Cache-Control | private | 響應 | 緩存該用戶的瀏覽器 |
Last-Modified | Thu, 30 Nov 2017 08:21:14 GMT | 響應 | 告訴瀏覽器服務端最後一次修改的時間 |
If-Modified-Since | Thu, 30 Nov 2017 08:21:14 GMT | 請求 | 若是瀏覽器中Last-Modofied有值,在請求中把值給If-Modified-Since,提交給服務端 |
ETag | 3df04c15b968d31:0 | 響應 | 該資源及其版本在服務端的惟一標識 |
If-None-Match | 3df04c15b968d31:0 | 請求 | 把上次請求中獲取到的ETag值,賦值給If-None-Match並提交給服務端 |
Vary | Accept-Encoding | 響應 | 從多個緩存副本中選擇匹配的版本 |
no-cache
: 使用no-cache
指令的目的是爲了防止從緩存中使用過時的資源,因此每次使用緩存時都要到服務端去驗證。從字面意思上很容易把no-cache
誤解成爲不緩存,但事實上no-cache
表明不緩存過時的資源,緩存會向源服務器進行有效期確認後處理資源。no-store
: 不存儲客戶端相關請求或服務器響應的任何內容,即真正的不緩存。若有不對,請多多指教。
參考: