搞Web開發的人,都會聽說過緩存,開發中偶爾會遇到換圖片、修改引入進來的腳本文件或者是替換Flash文件,你會發現運行出來的結果不變,這時候你肯定也會想過是緩存的原因,會把瀏覽器的緩存給清除掉。步驟可以如下清除瀏覽器緩存:
今天想寫寫ASP.NET緩存,搞Web開發,不使用緩存是不可能的。
緩存有分客戶端緩存與服務端緩存,但是通常使用服務端緩存。因為客戶端的請求都是服務端來響應,那么在服務端來做緩存的話,客戶端的請求都可以由緩存來響應。從而使響應的速度更快。緩存是什么?它就像一個時間片段的數據副本,在緩存的有效時間內,客戶的請求,服務器都只用相同的數據副本來進行響應。
就因為緩存的這種特征,它使得請求后的響應時間更短,有效提高了服務器的性能,降低帶寬的成本。總之,相同的環境下,使用緩存與不使用緩存,在響應時間比較長的情況下,使用緩存的響應速度會讓你驚嘆不已。但是緩存雖棒,也有不足之處。提高了響應速度,帶來了數據的不准確性。因為前面也說了緩存是一個時間片段的數據副本,也就是說數據經過增加、刪除、更改等加工之后,顯示給用戶看的效果還是原來那樣。這有時候會讓人很惱火,尤其像我這樣急性子的人。但使用緩存依賴就可以解決此問題。
同一個人,對於某些人來說,是好人,對於某些人來說,是壞人。所以對事對人來說,總不能以偏蓋全。避開缺點,發揮優勢,才是我們需要做的。緩存可以使用在加工頻率要求不是特別高的地方 。假如對於用戶來說,數據實時性並不特別重要,也就是對時間的制約不是特別高的話,那么使用緩存確實可以增速不少。
下面我們來看看服務端緩存與客戶端緩存。
服務端緩存:
(1)Session:針對小量數據,服務於單個用戶,默認失效時間為20分鍾。
包括三種實現方式,分別是:
=>InProc方式:
數據存儲在aspnet_wp.exe 進程中,數據會因為IIS的重啟而丟失。
=>StateServer方式 :
較InProc不同,可以存儲於不同的服務器中。
=>SQLServer:
數據存儲於數據庫中,數據不會因為IIS的重啟而丟失。
后兩種方法與InProc最大的區別在於,我們要確保緩存的數據是可序列化的。否則只能用第一種方式,為此我們要仔細分析從而選出最適合自己的方式.
使用方法:
//存數據
Session["key"] = value;
//取數據
Object value = Session["key"]
(2)Application:任意數據大小,服務於所有用戶,擁有整個應用程序的生命周期。通常是針對小數據存儲,像實現網站訪問量等。
與Session的使用方法相同:
//存數據
Application["key"] = value;
//取數據
Object value = Application["key"];
(3)Cache:任意數據大小,服務於所有用戶,程序指定生命周期。
移除Cache,我們可以使用Cache.Remove("key"),也可以根據緩存依賴關系來讓Cache失效。當依賴的關系有改動時,此時Cache會自動失效。
=》緩存依賴:緩存的生命周期依賴於數據來源的變化,緩存依賴有多種,限於篇幅,只介紹下面兩種。
I、依賴於文件或文件夾:當磁盤上的一個文件或文件夾發生變化時(修改或者是刪除)自動讓Cache失效。使用緩存依賴,你可以實例化微軟的CacheDependency對象,並給對象傳遞文件的路徑或者是文件夾的路徑。如果是文件夾的路徑,它會監視該文件夾下的所有文件和里面第一級子文件夾。
string cacheData="緩存內容"; CacheDependency fileDependency =new CacheDependency(Server.MapPath("test.xml")); Cache.Insert("ERROR_INFO", cacheData, fileDependency);
II、依賴於數據庫:當數據庫中的相關數據被修改時自動讓Cache失效。
依賴於文件或文件夾,微軟提供CacheDependency對象,但是依賴於數據庫,則需要使用另一個對象SqlCacheDependcy。
需要結合SQL Server 2005數據庫,目前還沒有Oracle數據庫的緩存依賴。
使用數據庫依賴,ASP.NET可以按如下方式實現:
第一步:web.config兩配置
一配置數據庫連接字符串:
二配置緩存依賴數據庫(緩存數據庫依賴主要是說明依賴哪個數據庫,下面的connectionStringName值與一中的name是一致的)<configuration>
...
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
...
</configuration>第二步:需要使用緩存數據庫的ASPX頁面再增加如下語句即可:<system.web>...<caching><sqlCacheDependency enabled = "true" pollTime = "1000" ><databases><add name="testCache"connectionStringName="ApplicationServices"pollTime = "1000" /></databases></sqlCacheDependency></caching>...</system.web><%@ Page Title="主頁" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="SqlCacheDenpendcy._Default" %><%@ OutputCache Duration="3600" SqlDependency="testCache:CacheTable" VaryByParam="none" %>
(4)ASP.NET 頁面輸出緩存 ---ASPX和ASCX頁面
在Web站點中,最簡單直接有效的方式可以使用頁面輸出緩存。通過緩存頁面來輸出,數據則不像依賴緩存那么准確,因為頁面是指定時間失效。這里的頁面包括ASPX頁面也包括ASCX用戶控件頁面。ASPX頁面是整頁面緩存,而ASCX用戶控件頁面則是局部緩存。兩者的使用方式一樣。
代碼跟與第數據庫依賴的第二步類似:
<%@ Page Title="主頁" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="SqlCacheDenpendcy._Default" %><%@ OutputCache Duration="60" VaryByParam="empNum" Location="Server"%>
參數解釋:
參數 說明 備注 Duration 頁或用戶控件進行緩存的時間(以秒計)。 在頁或用戶控件上設置該特性為來自對象的 HTTP 響應建立了一個過期策略,並將自動緩存頁或用戶控件輸出。
此特性必選。 如果未包含該屬性,將出現分析器錯誤。
除非你的Location=None,可以不添加此屬性,其余時候都是必須的。
Location OutputCacheLocation 枚舉值之一。 默認值為 Any。
Location當被設置為None時,其余的任何設置將不起作用;
Any——頁面被緩存在瀏覽器、代理服務器端和web服務器端;
Client——緩存在瀏覽器;
DownStream——頁面被緩存在瀏覽器和任何的代理服務器端;
None——頁面不緩存;
ServerAndClient——頁面被緩存在瀏覽器和web服務器端。包含在用戶控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 CacheProfile 與該頁關聯的緩存設置的名稱。 這是可選特性,默認值為空字符串 ("")。 包含在用戶控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 在頁中指定此屬性時,屬性值必須與 outputCacheSettings 節下面的 outputCacheProfiles 元素中的一個可用項的名稱匹配。 如果此名稱與配置文件項不匹配,將引發異常。 NoStore 一個布爾值,它決定了是否阻止敏感信息的二級存儲。 包含在用戶控件(.ascx 文件)中的 @ OutputCache 指令不支持此特性。 將此特性設置為 true 等效於在請求期間執行以下代碼:
Response.Cache.SetNoStore();ProviderName 一個字符串值,標識要使用的自定義輸出緩存提供程序。 此屬性僅在用戶控件(.ascx 文件)中受到支持。 它不受包含在 ASP.NET 頁(.aspx 文件)中的 @ OutputCache 指令的支持。 Shared 一個布爾值,確定用戶控件輸出是否可以由多個頁共享。 默認值為 false。 包含在 ASP.NET 頁(.aspx 文件)中的 @ OutputCache 指令不支持此特性。 SqlDependency 標識一組數據庫/表名稱對的字符串值,頁或控件的輸出緩存依賴於這些名稱對。 請注意,SqlCacheDependency 類監視輸出緩存所依賴的數據庫中的表,因此當更新表中的項時,使用基於表的輪詢時將從緩存中移除這些項。 如果以值 CommandNotification 使用通知(在 Microsoft SQL Server 2005 中),則最終會使用 SqlDependency 類向 SQL Server 2005 服務器注冊查詢通知。 SqlDependency 特性的 CommandNotification 值僅在網頁 (.aspx) 中有效。 用戶控件只能將基於表的輪詢用於 @ OutputCache 指令。
VaryByCustom 任何表示自定義輸出緩存要求的文本。 如果特性的賦值為 browser,緩存將隨瀏覽器名稱和主要版本信息的不同而異。 如果輸入自定義字符串,則必須在應用程序的 Global.asax 文件中重寫 GetVaryByCustomString 方法。 VaryByHeader 分號分隔的 HTTP 標頭列表,用於使輸出緩存發生變化。 將該特性設為多標頭時,對於每個指定標頭組合,輸出緩存都包含一個不同版本的請求文檔。
Accept-Language——代表請求頁面中用戶最希望的有優先級順序的人類語言列表;
User-Agent——代表請求頁面設備的類型;
Cookie——代表當前域名下創建的瀏覽器的cookie項。設置 VaryByHeader 特性將啟用在所有 HTTP 1.1 版緩存中緩存項,而不僅僅在 ASP.NET 緩存中進行緩存。 用戶控件中的 @ OutputCache 指令不支持此特性。
例如:設置VaryByHeader="Accept-Language"。
當網站有多種語言版本時,可以為每種語言都進行緩存。VaryByParam 分號分隔的字符串列表,用於使輸出緩存發生變化。 默認情況下,這些字符串對應於使用 GET 方法特性發送的查詢字符串值,或者使用 POST 方法發送的參數。 將該特性設置為多個參數時,對於每個指定參數組合,輸出緩存都包含一個不同版本的請求文檔。 可能的值包括 none、星號 (*) 以及任何有效的查詢字符串或 POST 參數名稱。 在 ASP.NET 頁和用戶控件上使用 @ OutputCache 指令時,需要此特性或 VaryByControl 特性。 如果沒有包含它,則發生分析器錯誤。 如果不希望通過指定參數來改變緩存內容,請將值設置為 none。 如果希望通過所有的參數值改變輸出緩存,請將特性設置為星號 (*))。
例如:
如果命令設置為:
<%@ OutputCache Duration="60" VaryByParam="ProductType" %>
當請求路徑 bitauto.com/test.aspx?ProductType=1發生時,會建立緩存當ProductType的值變為2時,系統會建立新的緩存,但是原來的緩存在有效期內並不會失效。相當於為不同的ProductType值建立了不同版本的緩存。如果熟悉.Net數據緩存的話,很類似於下面的用法。
Cache.Add(“productType1”,cachedObject)
Cache.Add(“productType2”,cachedObject)VaryByControl 分號分隔的字符串列表,用於改變用戶控件的輸出緩存。 這些字符串代表用戶控件中聲明的 ASP.NET 服務器控件的 ID 屬性值。 在 ASP.NET 頁和用戶控件上使用 @ OutputCache 指令時,需要此特性或 VaryByParam 特性。
例如下面:根據頁面上下拉列表控件的選擇的值不同進行不同的緩存輸出
<%@ OutputCache Duration="100" VaryByControl="dropTest"%>VaryByContentEncodings 以分號分隔的字符串列表,用於更改輸出緩存。 將 VaryByContentEncodings 特性用於 Accept-Encoding 標頭,可確定不同內容編碼獲得緩存響應的方式。
客戶端緩存:
上面介紹了部分服務端緩存的方法,但有的時候我們為了提高服務器的性能我們也需要把數據緩存到客戶端。使用這種緩存機制,可以適當緩解服務器壓力,不過在客戶端緩存數據會有一定的安全性問題。
Cookies:在Web站點中應用非常廣,它可以非常方便的在客戶端與服務器端之間進行相互訪問,最大只能支持4KB,所以一般只能保存小數據。可以儲存到客戶端的硬盤或內存。
if (this.Request.Cookies["key"] == null) { this.Response.Cookies.Add(new HttpCookie("key","test")); } else { this.Response.Write(this.Request.Cookies["key"].Value); }
題外話,客戶端緩存及服務端緩存,在網上查找了很多相關的文章,內容都很豐富,也很詳細,通過整理學習,並寫成博客,我覺得這種學習方式挺好的。雖然寫作能力有高下之分,但是長期以往地堅持,笨鳥也可以先飛。至此,本文告一段落,希望能拋我的磚引大家的玉 :)