ASP.NET 2.0中的Output Caching

本文英文原版以及代碼下載:
http://aspnet.4guysfromrolla.com/articles/121306-1.aspx

ASP.NET 2.0中的Output Caching

導言:

要想提升web application的性能的話,使用caching技術是肯定能實現的.Caching利用一些操作將結果存儲在一個本地可以快速訪問的地方.在ASP.NET version 1.0裏引入了2種技術:

.Output Caching -在特定的時間段內,將一個ASP.NET web頁面或User Control的完整代碼數據進行緩存.

.Data Caching—將objects對象存儲在web server的內存裏,這些存儲在內存裏的數據可以通過編程來訪問.

關於ASP.NET 1.x緩存技術的更深入的探討,可參閱Scott McFarland的文章《Caching with ASP.NET》,以及Steve Smith的《ASP.NET Caching: Techniques and Best Practices》.

在ASP.NET 2.0,緩存系統已經擴展到包含SQL cache dependencies, cache profiles, 以及post-cache substitution.在ASP.NET 2.0 QuickStarts(http://quickstarts.asp.net/QuickStartv20/aspnet)的“Caching for Performance”部分,對ASP.NET 2.0裏的caching進行了很好的綜述.本文探究ASP.NET 2.0中的output caching,最開始我們將對output caching進行綜述,接着我們將詳細的考察如何利用fragment caching和post-cache substitution技術來創建一個包含cached 和 non-cached代碼的頁面.

Output Caching綜述

Output caching是這樣提升ASP.NET應用程序的性能的,它將一個ASP.NET web頁面的代碼緩存起來,而不是對頁面進行重新繪製.打個比方,比如有一個ASP.NET頁面,該頁面將一個名爲Employees的數據庫的記錄顯示出來, 顧名思義,該表存儲的是當前員工的信息.如果不進行緩存的話,每當訪問該頁面的時候,都會造成對數據庫的連接,對錶的請求,最後將結果返回給請求客戶端.但是,僱員信息隔多久纔會有更改的情況呢?可能一天,那麼對數據庫的頻繁請求也太過了吧.如果利用output caching的話,在初次對頁面的訪問時,對要返回的HTML將在一定的時間進行緩存.在這個時間內,如果某個用戶請求該頁面,就將緩存數據返回。這樣便節省了數據庫訪問和頁面繪製的系統開銷.

這就是一個簡單的output caching。要貫徹它的話,只需要簡單的在頁面頂部添加聲明
<% @OutputCache %> ,像這樣:

<%@ Page ... %>
<%@ OutputCache Duration="duration" VaryByParam="paramList" %>

其中,duration就是要緩存的秒數. paramList是一系列的參數,這些參數的值將對緩存產生影響.打個比方,如果某個頁面只需要將某個特定部門的員工信息顯示出來,而到底是哪個部門則由查詢參數來決定,在這種情況下,我們就可以利用該參數來對緩存施加影響.具體來說,比如我們想通過訪問ShowEmployees.aspx?DepartmentID=departmentID這個頁面來展示某個部門的員工,如果沒有通過參數對緩存施加影響,當一個用戶訪問 ShowEmployees.aspx?DepartmentID=Sales頁面時,那麼將返回Sales部門的員工信息,並對頁面進行緩存,而如果在緩存期間恰好有另一個用戶訪問ShowEmployees.aspx?DepartmentID=IT頁面,那麼他將會看到緩存的sales部門而不是IT部門的員工信息.

爲解決這個問題,我們僅僅需要通過參數DepartmentID來使output cache引擎來實現多樣化緩存,如下:

<%@ OutputCache Duration="duration"  VaryByParam="DepartmentID" %>

要通過所有的參數來實現緩存多樣化,可以使用星號(*);如果不使用參數,使用"None".

Output Caching技巧

雖然實現output caching很容易—僅僅添加<%@ OutputCache %>標記,不過仍然有一些技巧值得我們關注.正如前面探討的,對緩存實施多樣化很重要,這樣我們便可以根據輸入參數的值進行恰當的緩存.除了VaryByParam,還可以考慮使用VaryByX操作。比如,我們可以根據瀏覽器的不同實施不同的緩存,還有如果有一個多語言版本的網站,你可以根據使用語言情況的不同來進行不同的緩存.關於根據HTTP headers 或 custom values的不同來進行不同緩存的具體細節可參閱文章《ASP.NET Caching: Techniques and Best Practices》

考察Ouptut Caching的內部機制

在ASP.NET裏,Output caching是作爲一個HTTP Module來貫徹的.具體來說就是 System.Web.Caching命名空間裏的OutputCacheModule類.一個HTTP Module對一個request 的生命週期內的事件進行監聽,如果觸發了某個具體的事件就執行代碼.該OutputCacheModule HTTP Module對應ResolveRequestCache 和 UpdateRequestCache.

在ResolveRequestCache事件裏,該module判斷是否有output caching請求,如果是,則返回一個緩存版本,如果沒有所需要的緩存版本的話就呈現正常頁面.在事件結束時又觸發 UpdateRequestCache事件,該module將對rendered output進行緩存(如果該頁面被設置爲支持output caching的話).下圖對OutputCacheModule module要執行的這些作業進行了簡單的描述,雖然簡單了點,但概括了總體的流程.


                                                                         圖1

如果想在緩存到期之前就終止緩存的話,有2個選擇。一是通過編程調用 Response.RemoveOutputCacheItem(path)方法來移除某個頁面的output cached,其中path是該頁面的相對路徑.另外,你還可以對output cache添加外部依賴,就像在文章
《Caching Page Output with Cache Key Dependencies》裏探討的那樣.比如SQL Cache Dependencies,詳情請參閱ASP.NET 2.0 QuickStarts的的《SQL Cache Invalidation》部分(http://quickstarts.asp.net/QuickStartv20/aspnet/doc/caching/SQLInvalidation.aspx).


僅僅對頁面的一部分進行Output Caching

默認情況下,output caching是針對整個頁面緩存.不過在某些時候,我們希望頁面的某些部分保持“刷新”(dynamic)。我們希望將那些系統開銷大,不怎麼變化的項——比如,要顯示的數據進行緩存,而將廣告、與某個用戶相關的數據或其它頻繁改變的信息保持"刷新".在ASP.NET 1.x裏,我們只能通過fragment caching來實現,這樣就達到了“頁面的局部緩存而其它部分保持刷新”的目的.在ASP.NET 2.0也支持fragment caching,同時引入了post-cache substitution model,利用它我們可以實現“緩存頁面,且保持某些部分刷新”的效果.讓我們先看看fragment caching,再將注意力轉移到post-cache substitutions.

Fragment caching原理在於創建一個包含User Control的頁面,該頁面沒有用到output caching而由其包含的User Control使用output caching.本文的下載代碼裏包含了一個簡單的示例,裏面包含一個CachedUserControl.ascx用戶控件,它將一個數據庫表的記錄顯示出來,同時將檢索數據的date/time值也反映出來.該User Control包含一個 <% @OutputCache %>聲明,如下:

<%@ Control ... %>
<%@ OutputCache Duration="15" VaryByParam="None" %>

... markup that displays records from a database table ...

包含該User Control的頁面並不包含<% @OutputCache %>聲明.最終的結果是每次登錄頁面的時候都會重新繪製頁面,但在每隔15秒的時間間隔內,該User Control只呈現一次(自然,也只訪問數據庫一次).

如下的截屏顯示的是初次登錄頁面的情形。我們注意到頁面和User Control顯示的date/time值是一樣的.隔幾秒後再次登錄頁面,因爲對User Control進行了緩存,頁面的date/time值改變了,而User Control顯示的date/time值依然是初次登錄時的值.

 

圖2

 

圖3

除了本文的下載代碼外,你還可以參閱文章《如何使用 Visual C# .NET 在 ASP.NET 中執行片段緩存》(http://support.microsoft.com/default.aspx/kb/308378),看如何按部就班的使用fragment caching.

通過Post-Cache Substitutions對緩存頁面的局部保持"刷新"

ASP.NET 2.0新增加了一項技術post-cache substitutions—它可以將緩存的和需要"刷新"的內容有機的集合起來.就像其名稱揭示的那樣,該方法可以允許在一個使用了output caching的頁面裏,對緩存的內容實施“刷新”.你可以通過2種途徑來使用它:

.Declaratively—使用Substitution控件來指定頁面的動態刷新部分(dynamic portion). 你需要創建一個方法,用這些控件來調用這個方法來獲取動態刷新部分的rendered markup.

.Programmatically— Response.WriteSubstitution(callback)method可以通過編程的方式注入一個response substitution模塊。其中,參數callback是對某個方法的委託(delegate),這個方法被調用來獲取要發送出去的markup.

要使用declarative方式的話,你只需要在output cached頁面上要注入動態數據(dynamic data)的地方添加一個Substitution控件,如下:

<%@ Page ... %>
<%@ OutputCache Duration="duration" VaryByParam="paramList" %>
...
   <asp:Substitution ID="id" runat="server" MethodName="method" />
...

其中MethodName(string)屬性指定了一個頁面後臺代碼類裏的一個靜態方法,該方法接受一個HttpContext object對象,返回string.比如,假設有一個包含緩存數據的頁面,同時我們又想在頁面上包含一個動態信息(比如,一個廣告).這種情況下,我們在頁面上希望顯示該信息的區域添加一個Substitution控件:

<asp:Substitution ID="DynamicMessage" runat="server" MethodName="GetMessage" />

這裏我們將MethodName指定爲GetMessage. 因此,我需要在頁面的後臺代碼裏創建一個名爲GetMessage,且返回一個string的靜態方法:

'VB
Private Shared Function GetMessage(ByVal context As HttpContext) As String
   Return "This ad brought to you by the time " & DateTime.Now.ToString()
End Function


// C#
private static string GetMessage(HttpContext context)
{
   return "This ad brought to you by the time " + DateTime.Now.ToString();
}

當登錄頁面時,像通常那樣將頁面內容進行緩存。在後續的登錄時,雖然頁面仍然被緩存,但OutputCacheModule會調用GetMessage方法並將其結果顯示在頁面上恰當的位置.

結論

ASP.NET的output caching屬性允許對一個頁面或User Control的整個HTML輸入進行緩存,這有助於提升應用程序的總體性能.output caching邏輯是由OutputCacheModule來處理的.有時候,需要對頁面的某個部分進行緩存,而其它部分則要保持刷新狀態,爲此,ASP.NET 2.0提供了2種解決辦法:fragment caching 和 post-cache substitutions.對fragment caching而言,沒有對頁面實施output caching,對要實行緩存的部分我們可以使用User Control來實行,該用戶控件被設置爲使用output caching.另一個方法是使用post-cache substitution,此時需要設置頁面使用output caching.將Substitution控件添加到頁面以指出頁面的哪個區域的內容在每次登錄時都要進行動態更新,而不管頁面是否被緩存.Post-cache substitutions是ASP.NET 2.0裏新增加的功能.

祝編程快樂!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章