1. INTRODUCTION
大量的網站頁面是採用動態的方式,根據用戶提交的不同請求創建生成頁面。正如我們所知的,動態頁面有助於根據用戶要求來提供定製的動態內容。動態頁面也利於獲取在數據庫中每時每刻更新的資料。缺點是爲每個用戶請求生成同一頁面增加了系統開銷。
ASP.NET 提供了緩存技術有助於我們最大程度地解決這個問題。它能緩存輸出的頁面,保存在存儲器當中,緩存用戶請求的內容。緩存的特點可以根據不同方式來定製的。
本文主要介紹ASP.NET的緩存技術。介紹其使用方法,以及客戶端緩存存在的問題。
2. ASP.NET CACHE
緩存是把應用程序中需要頻繁、快速訪問的數據保存在內存中的編程技術。ASP.NET提供三種主要形式的緩存:頁面級輸出緩存、用戶控件級輸出緩存(或稱爲片段緩存)和緩存API。輸出緩存和片段緩存的優點是非常易於實現,在大多數情況下,使用這兩種緩存就足夠了。而緩存API則提供了額外的靈活性(實際上是相當大的靈活性),可用於在應用程序的每一層利用緩存。本文只介紹頁面級緩存和用戶控件級緩存。
2.1. Page Caching
作爲最簡單的緩存形式,輸出緩存只是在內存中保留爲響應請求而發送的 HTML 的副本。其後再有請求時將提供緩存的輸出,直到緩存到期,這樣,性能有可能得到很大的提高(取決於需要多少開銷來創建原始頁面輸出 - 發送緩存的輸出總是很快,並且比較穩定)。
要實現頁面輸出緩存,只要將一條 OutputCache 指令添加到頁面即可:
<%@ OutputCache Duration="60" VaryByParam="*" %>
如同其他頁面指令一樣,該指令應該出現在ASPX頁面的頂部,即在任何輸出之前。它支持五個屬性(或參數),其中兩個是必需的。
Duration:必需屬性。頁面應該被緩存的時間,以秒爲單位。必須是正整數。
Location:指定應該對輸出進行緩存的位置。如果要指定該參數,則必須是下列選項之一:Any、Client、Downstream、None、Server 或 ServerAndClient。
VaryByParam:必需屬性。Request 中變量的名稱,這些變量名應該產生單獨的緩存條目。"none" 表示沒有變動。"*" 可用於爲每個不同的變量數組創建新的緩存條目。變量之間用 ";" 進行分隔。
VaryByHeader:基於指定的標頭中的變動改變緩存條目。
VaryByCustom:允許在 global.asax 中指定自定義變動(例如,"Browser")。
利用必需的 Duration 和 VaryByParam 選項的組合可以處理大多數情況。例如,如果您的產品目錄允許用戶基於 categoryID 和頁變量查看目錄頁,您可以用參數值爲 "categoryID;page" 的 VaryByParam 將產品目錄緩存一段時間(如果產品不是隨時都在改變,一小時還是可以接受的,因此,持續時間是 3600 秒)。這將爲每個種類的每個目錄頁創建單獨的緩存條目。每個條目從其第一個請求算起將維持一個小時。
VaryByHeader 和 VaryByCustom 主要用於根據訪問頁面的客戶端對頁面的外觀或內容進行自定義。同一個 URL 可能需要同時爲瀏覽器和移動電話客戶端呈現輸出,因此,需要針對不同的客戶端緩存不同的內容版本。或者,頁面有可能已經針對 IE 進行了優化,但需要能針對 Netscape 或 Opera 完全降低優化(而不僅僅是破壞頁面)。
2.2. Fragment caching
ASP.NET提供了部分緩存或區域緩存Web表單的功能。當希望在特定的頁面上實現對緩存更多的控制時,可以使用該技術。
爲了指定應該被緩存的用戶控件,我們利用 @OutputCache 指令,就象整個頁面緩存的用法一樣。
<%@ OutputCache Duration=10 VaryByParam="*" %>
該示例將緩存用戶控件60秒,並且將針對查詢字符串的每個變動、針對此控件所在的每個頁面創建單獨的緩存條目。
<%@ OutputCache Duration="60" VaryByParam="none"
VaryByControl="CategoryDropDownList" %>
該示例將緩存用戶控件60秒,並且將針對CategoryDropDownList控件的每個不同的值、針對此控件所在的每個頁面創建單獨的緩存條目。
還可以通過設置屬性Shared=”true”,讓使用它的所有頁面共享這個控件緩存。
3. CONCLUSION AND SUGGESTION
應該在應用程序的每一層都實現緩存。向數據層、業務邏輯層、UI 或輸出層添加緩存支持。內存現在非常便宜 — 因此,通過以智能的方式在整個應用程序中實現緩存,可以獲得很大的性能提高。
緩存是一種無需大量時間和分析就可以獲得“足夠良好的”性能的方法。這裏再次強調,內存現在非常便宜,因此,如果您能通過將輸出緩存 30 秒,而不是花上一整天甚至一週的時間嘗試優化代碼或數據庫就可以獲得所需的性能,您肯定會選擇緩存解決方案(假設可以接受 30 秒的舊數據)。緩存正是那些利用 20% 付出獲得 80% 回報的特性之一,因此,要提高性能,應該首先想到緩存。不過,如果設計很糟糕,最終卻有可能帶來不良的後果,因此,您當然也應該儘量正確地設計應用程序。但如果您只是需要立即獲得足夠高的性能,緩存就是您的最佳選擇,您可以在以後有時間的時候再儘快重新設計應用程序。
ASP.NET緩存和IE緩存並不是同一個概念,IE緩存可能會導致錯誤發生,而且很難控制,可以考慮禁止IE緩存,而只採用ASP.NET緩存機制。
針對我們的Web系統的特殊性,存在大量的頁面針對不同的用戶顯示不同的數據,因此在採用ASP.NET緩存機制時,請格外小心。可以考慮在緩存機制使用時增加一些必要的參數。
- using System;
- using System.Collections;
- using System.Text.RegularExpressions;
- using System.Web;
- using System.Web.Caching;
- namespace Ycweb.Components
- {
- public class SiteCache
- {
- private static readonly Cache _cache;
- public static readonly int DayFactor;
- private static int Factor;
- public static readonly int HourFactor;
- public static readonly int MinuteFactor;
- static SiteCache()
- {
- DayFactor = 17280;
- HourFactor = 720;
- MinuteFactor = 12;
- Factor = 5;
- _cache = HttpRuntime.Cache;
- }
- private SiteCache()
- {
- _cache.Insert("", "", "", "", "", "", "");
- }
- public static void Clear()
- {
- IDictionaryEnumerator enumerator = _cache.GetEnumerator();
- while (enumerator.MoveNext())
- {
- _cache.Remove(enumerator.Key.ToString());
- }
- }
- public static object Get(string key)
- {
- return _cache[key];
- }
- public static void Insert(string key, object obj)
- {
- Insert(key, obj, null, 1);
- }
- public static void Insert(string key, object obj, int seconds)
- {
- Insert(key, obj, null, seconds);
- }
- public static void Insert(string key, object obj, CacheDependency dep)
- {
- Insert(key, obj, dep, HourFactor * 12);
- }
- public static void Insert(string key, object obj, int seconds, CacheItemPriority priority)
- {
- Insert(key, obj, null, seconds, priority);
- }
- public static void Insert(string key, object obj, CacheDependency dep, int seconds)
- {
- Insert(key, obj, dep, seconds, CacheItemPriority.Normal);
- }
- public static void Insert(string key, object obj, CacheDependency dep, int seconds, CacheItemPriority priority)
- {
- if (obj != null)
- {
- _cache.Insert(key, obj, dep, DateTime.Now.AddSeconds((double)(Factor * seconds)), TimeSpan.Zero, priority, null);
- }
- }
- public static void Max(string key, object obj)
- {
- Max(key, obj, null);
- }
- public static void Max(string key, object obj, CacheDependency dep)
- {
- if (obj != null)
- {
- _cache.Insert(key, obj, dep, DateTime.MaxValue, TimeSpan.Zero, CacheItemPriority.AboveNormal, null);
- }
- }
- public static void MicroInsert(string key, object obj, int secondFactor)
- {
- if (obj != null)
- {
- _cache.Insert(key, obj, null, DateTime.Now.AddSeconds((double)(Factor * secondFactor)), TimeSpan.Zero);
- }
- }
- public static void Remove(string key)
- {
- _cache.Remove(key);
- }
- public static void RemoveByPattern(string pattern)
- {
- IDictionaryEnumerator enumerator = _cache.GetEnumerator();
- Regex regex1 = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
- while (enumerator.MoveNext())
- {
- if (regex1.IsMatch(enumerator.Key.ToString()))
- {
- _cache.Remove(enumerator.Key.ToString());
- }
- }
- }
- public static void ReSetFactor(int cacheFactor)
- {
- Factor = cacheFactor;
- }
- }
- }
- 轉載於:http://www.cnblogs.com/aspsir/archive/2006/07/27/461229.html