前言
眾所周知,各個大型網站為了提升網站訪問效能或多或少的都有用一些緩衝來提升應用效能,其中最為常用的可能就是產生HTMl頁面了,這種方法從某種意義上來說,可以納入檔案快取的範圍裡。不過這種做法有一些弊端(對我來說),沒有一套完整的HTML檔案管理機制,導致大量的HTML代碼的管理是件非常頭痛的事情。
我們今天就來講講另外一種我們很常用並且很簡單的做法,那就是 ASP.NET 的輸出緩衝 OutputCache
OutputCache
對於各位做WEB開發的 Neter 來說,想必OutputCache一定不會陌生了,在 WebForm 中,我們在aspx頁面頂端包含 OutputCache 設定 : <%@OutputCache VaryByParam="none" Duration="10" %>,在 ASP.NET MVC 中,我們在 Controller/ Action 上添加該屬性來快取資料來提升程式效能:
public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); } [OutputCache(Duration = 10, VaryByParam = "none")] public ActionResult About() { return View(); } }
OutputCache 的缺點
那麼 OutputCache 到底有什麼缺點呢?我們都知道 OutputCache 輸出緩衝是儲存在記憶體中的,也就是說這種做法就已經限定只能用在小型網站中,因為如果我們的網站中包含大量的基於記憶體的緩衝,恐怕會非常消耗主機記憶體的。
OutputCache 完善
鑒於OutputCache 基於記憶體儲存這一問題,我們對 OutputCache 來進行擴充解決這一問題,此時就要用到 .net framework 4 中的 OutputCacheProvider,藉助OutputCacheProvider,我們可以有多種選擇建立自己的緩衝,本節我就來擴充下 OutputCache 來建立自訂檔案快取。
藉助OutputCacheProvider擴充OutputCache建立自訂檔案快取
建立類:FileCacheProvider,引入 using System.Web.Caching; 命名空間,繼承自 OutputCacheProvider 抽象類別,重寫 四個方法 :
Add 方法,將指定項插入輸出緩衝中。
Get 方法,返回對輸出緩衝中指定項的引用。
Remove 方法,從輸出緩衝中移除指定項。
Set 方法,將指定項插入輸出緩衝中,如果該項已緩衝,則覆蓋該項。
public class FileCacheProvider : OutputCacheProvider { public string CachePath { get; set; } private string ConvertKeyToPath(string key) { string file = key.Replace('/', '-'); file += ".txt"; return Path.Combine(CachePath, file); } public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { base.Initialize(name, config); //讀取 CachePath = HttpContext.Current.Server.MapPath(config["cachePath"]); } public override object Add(string key, object entry, DateTime utcExpiry) { object obj = Get(key); if (obj != null) { return obj; } Set(key, entry, utcExpiry); return entry; } public override object Get(string key) { string path = ConvertKeyToPath(key); if (!File.Exists(path)) { return null; } CacheItem item = null; using (FileStream file = File.OpenRead(path)) { var formatter = new BinaryFormatter(); item = (CacheItem)formatter.Deserialize(file); } if (item.ExpiryDate <= DateTime.Now.ToUniversalTime()) { //log Remove(key); return null; } return item.Item; } public override void Set(string key, object entry, DateTime utcExpiry) { CacheItem item = new CacheItem(entry, utcExpiry); string path = ConvertKeyToPath(key); using (FileStream file = File.OpenWrite(path)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(file, item); } } public override void Remove(string key) { string path = ConvertKeyToPath(key); if (File.Exists(path)) { File.Delete(path); } } } [Serializable] public class CacheItem { public DateTime ExpiryDate; public object Item; public CacheItem(object entry, DateTime utcExpiry) { Item = entry; ExpiryDate = utcExpiry; } }
執行個體程式中,我將緩衝放在 Config 檔案配置的 cachePath 目錄中,具體請看 Initialize 方法。
設定檔
需要在Web.Config 檔案中配置緩衝處理常式驅動
<system.web> <caching> <outputCache defaultProvider="FileCache"> <providers> <add name="FileCache" type="FileCache.Provider.FileCacheProvider" cachePath="~/Cache"/> </providers> </outputCache> </caching>
如何使用?
以上配置好之後,使用就很容易了,因為是對 Asp.NET 輸出緩衝 OutputCache 進行了擴充,所以使用方式 和之前的用法一樣,我在MVC中使用如下:
namespace FileCache.Controllers{ public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); } [OutputCache(Duration = 10, VaryByParam = "none")] public ActionResult About() { return View(); } }}
可以看到,我在 About Action 上打快取標籤 [OutputCache(Duration = 10, VaryByParam = "none")] ,設定緩衝時間10分鐘,並且不根據任何參數重新緩衝,運行,可以再配置好的 Cache 檔案下看到快取檔案:
運行程式後,訪問 About 頁面,將會看到在Cache檔案夾產生了快取檔案。
注意事項
我是在項目中提前建立好了 Cache 檔案夾,當然這個檔案夾名稱可以隨便取了,只需要在 Web.Config 映射正確即可,如果您運行報錯,可能是由於該檔案夾不存在,或者您可以再 緩衝擴代碼中判斷一下是否存在 Cache 檔案夾,沒有則程式建立即可。
遺留問題
以上我們可以看到是將快取檔案儲存成 txt 文本,那麼我們是否可以將其儲存為xml 格式檔案以及哪種格式效能好呢?如果選用 xml ,可以進一步修改使用泛型類來解決 不同對象的xml序列化問題。若您有更好的建議,不妨提出。