摘要:介紹緩存的基本概念和經常使用的緩存技術,給出了各類技術的實現機制的簡單介紹和適用範圍說明,以及設計緩存方案應該考慮的問題(共17頁)html
· 性能——將相應數據存儲起來以免數據的重複建立、處理和傳輸,可有效提升性能。好比將不改變的數據緩存起來,例如國家列表等,這樣能明顯提升web程序的反應速度;web
· 穩定性——同一個應用中,對同一數據、邏輯功能和用戶界面的屢次請求時常常發生的。當用戶基數很大時,若是每次請求都進行處理,消耗的資源是很大的浪費,也同時形成系統的不穩定。例如,web應用中,對一些靜態頁面的呈現內容進行緩存能有效的節省資源,提升穩定性。而緩存數據也能下降對數據庫的訪問次數,下降數據庫的負擔和提升數據庫的服務能力;算法
· 可用性——有時,提供數據信息的服務可能會意外中止,若是使用了緩存技術,能夠在必定時間內仍正常提供對最終用戶的支持,提升了系統的可用性。sql
在深刻介紹緩存技術以前,須要對狀態有一個認識,由於緩存能夠說是狀態管理的框架。理解狀態的含義和它的一些特性——好比生存期和生存範圍——對決定是否緩存和選擇合適的緩存技術有很大幫助。狀態是指一些數據,在應用系統某個時間點上,數據的狀態和條件。這些數據多是永久性的存儲在數據庫中,多是隻在內存裏停留一會,也多是按照某個邏輯存活(好比多長時間後釋放),它的應用範圍多是全部用戶可訪問,多是單個用戶有權限;數據庫
生存期是指數據保持有效性的時間區間,也就是從建立到移除的時間間隔。一般的生存期有如下幾種:編程
·永久狀態Permanent State——應用程序使用的永久數據;windows
·進程狀態Process State——只在進程週期內有效;瀏覽器
·會話狀態Session State——和特定的用戶會話有關;緩存
·消息狀態Message State——處理某個消息的時間內有效;安全
狀態的範圍指對該狀態有訪問權限的物理或邏輯範圍。
·物理範圍指能夠被訪問到的狀態數據存放的物理位置,一般包括:
一、 組織Organization——在一個組織內的全部應用程序能夠訪問狀態數據;
二、 場Farm——在應用場範圍內的任何機器上均可以訪問;
三、 機器Machine——單個機器範圍內能夠訪問;
四、 進程Process——進程內的訪問許可;
五、 應用域AppDomain——應用程序域內的訪問許可。
·邏輯範圍指可訪問狀態數據的邏輯範圍,常見的有:
一、 應用程序Application;
二、 業務流程Business Process;
三、 角色Role;
四、 用戶User;
緩存的狀態數據只是主數據(Master State Data)的快照,因爲數據源可能被修改,因此狀態數據就有會陳舊的特性。合理利用此特性和將數據陳舊的負面影響最小化是緩存狀態數據的一個重要任務。你能夠以一下方式定義數據的陳舊依據:
·主數據更改的可能性——隨着時間的推動,主數據更改的多是否大大增長?安照這一點來決定緩存狀態數據的陳舊;
·更改的相關性——主數據更新時,緩存的狀態數據不相應更新是否是形成影響系統的使用?好比,更改系統的外觀風格並不會對業務形成很大影響。
緩存狀態數據的陳舊對業務流程的影響稱爲容忍度,應用系統的能夠爲不能容忍(No Tolerance)和必定程度的容忍(some Tolerance),前者必須和主數據同步更新,後者容許必定時間或必定範圍的陳舊,判斷標準就是對業務流程的影響度。
狀態的另外一個屬性是在不一樣階段的表現形式。在數據庫中存儲的是原始格式的數據,業務流程中的是處理過的數據,給最終用戶呈現的則是另外的形式。以下表所示:
表現形式 |
描述 |
舉例 |
原始數據 |
數據的原始形式 |
如數據庫中的數據 |
處理過的數據 |
業務流程中對原始數據加工後的數據 |
業務過程當中的數據形式 |
呈現形式 |
可呈現給最終用戶的形式 |
HTML或可理解的文字說明 |
當決定緩存數據時,應該考慮緩存哪一個階段(哪一種形式)的狀態數據。如下方針有助於你作決定:
· 當業務邏輯能夠容忍緩存數據的陳舊時就緩存原始數據;原始數據能夠緩存在數據庫訪問組件和服務代理中;
·緩存處理過的數據以減小處理時間和資源;處理過的數據能夠緩存在業務邏輯組件和服務接口中。
·當須要呈現的數據量很大而且控件的呈現時間很長時,緩存呈現數據(好比包含大數據量的Treeview控件)。這種數據應該被緩存在UI控件中。
在應用程序中緩存數據有如下好處:
·減小交互的通信量——緩存數據能有效減小在進程和機器間的傳輸量;
·下降系統中的處理量——減小處理次數;
·下降須要作的磁盤訪問次數——好比緩存在內存中的數據。
緩存數據只是一份主數據的拷貝,它可能在內存中或以不一樣的表現形式保存在硬盤上,也就是說,離說句的使用者越近越好。因此,除了考慮要緩存哪些數據之外,數據緩存在哪裏也是一個主要的考量點。這個問題分爲如下兩個範圍:
一、 存儲類型Storage Type——數據可用的物理存儲位置;
二、 層間的架構元素(Layered architecture elements)——數據可用的邏輯存儲位置。
緩存有不少實現方法,全部這些能夠被分爲兩類,基於內存的緩存和基於磁盤的緩存:
一、 內存駐留緩存——包含在內存中臨時存儲數據的全部實現方法,一般在如下狀況下使用:
a) 應用程序頻繁使用一樣的數據;
b) 應用程序須要常常獲取數據;
經過將數據保留在內存中,你能夠有效下降昂貴的磁盤訪問操做,也能夠經過將數據保留在使用者進程中來最大程度的減小跨進程的數據傳輸。
二、 磁盤駐留緩存——這種技術包含全部使用磁盤做爲存儲介質的緩存技術,如文件和數據庫。在如下狀況下基於磁盤的緩存是頗有效的:
a) 處理大數據量時;
b) 應用服務提供的數據可能並非總能使用(好比離線的狀況);
c) 緩存的數據必須能在進程回收和機器重啓的狀況下保持有效;
經過緩存處理過的數據,你能夠有效下降數據處理的負擔,同時可減小數據交互的代價。
應用程序中的每一個邏輯層的組件都會處理數據,下圖標識了一些通用組件:
當使用這些組件進行工做時,你須要考慮哪些數據能夠被緩存起來,還有以哪一種方式進行緩存會對程序的總體性能和可用性有幫助,以上的這些元素均可以緩存相應的數據。固然,要考慮的遠不止這些。
當設計一個緩存方案時,不但要考慮緩存哪些數據、數據緩存到哪裏,還有其它的因素須要考慮。
當決定是否緩存一個對象時,關於數據的格式和訪問機制,你須要考慮三個主要問題:
一、 線程安全——當緩存的內容能夠被多個線程訪問時,使用某種鎖定機制來保證數據不會被兩個線程同時操做;
二、 序列化——將一個對象緩存時,須要將它序列化以便保存,因此包緩存的對象必須支持序列化;
三、 規格化緩存數據——緩存數據時,相對於要使用的數據格式而言,要保證數據的格式是優化過的。
在使用緩存數據前,必須將數據加載到緩存中,有兩種機制來加載數據:
·提早加載Proactive Load——使用這種方式時,你提早將全部的狀態數據加載到緩存中,可能在應用程序或線程啓動時進行,而後在應用程序或線程的生存期內一直緩存;
·動態加載Reactive Load——或稱反應式加載,當使用這種方法時,在應用程序請求數據時取到數據,而且將它緩存起來以備後續使用。
另一個關鍵因素是如何保持緩存數據和主數據(文件或數據庫或其餘的應用程序資源)的一致性,你能夠定義過時策略來決定緩存中的內容,如已經緩存的時間或者收到其餘資源的通知。
當緩存數據時,須要很是清楚緩存中數據的潛在安全威脅。緩存中的數據可能會被別的進程訪問或修改,而此進程對主數據是沒有權限的。緣由是當數據存儲在原始位置時,有相應的安全機制來保護它,當數據被帶出傳統的安全邊界時,須要有同等的安全機制。
當你緩存數據時,應用系統須要的維護工做加大了。在發佈應用程序時,須要配置相應的屬性,好比緩存的大小限制和清除策略。同時要使用某種機制來監控緩存的效率(好比事件日誌和性能計數器)
第一節內容簡單介紹了緩存技術中的概念、緩存數據的緣由和方案、優點、實施緩存方案時的考慮等基本內容。如今你對緩存中涉及的內容有了一個大體瞭解,下面着重介紹可用的緩存技術。
本節將介紹如下技術:
使用Asp.Net緩存;
使用Remoting Singleton緩存;
使用內存映射文件;
使用SQL Server緩存;
使用靜態變量緩存;
使用Asp.net 會話狀態(Session State);
使用Asp.net客戶端緩存和狀態;
使用Internet Explorer緩存。
將經常使用的數據保存在內存中對asp的開發人員來講並不陌生,Session對象和Application對象提供鍵值對來緩存數據,Session對象保存和單個用戶有關的數據,Application對象可保留和應用程序有關的數據,每一個用戶均可以訪問。
在Asp.net中,提供了專門用於緩存數據的Cache對象,它的應用範圍是應用程序域。生存期是和應用程序緊密相關的,每當應用程序啓動的時候就從新建立Cache對象。它域Application對象的主要區別就是提供了專門用於緩存管理的特性,好比依賴和過時策略。
你可使用Cache對象和它的屬性來實現高級的緩存功能,同時能夠利用Asp.net Cache來對客戶端輸出的響應內容進行緩存。關於Asp.net中的緩存技術,有如下內容要介紹:
Cache對象定義在System.Web.Caching命名空間,可使用HttpContext類的Cache屬性或Page對象的Cache屬性來獲得Cache的引用,Cache對象除了存儲鍵值對之外,還能夠存儲.net框架的對象。下面介紹相應的依賴和過時策略。
當向緩存中加數據時,能夠指定它的依賴關係來實如今某些狀況下強制移除它。可用的方案包括如下幾種:
·文件依賴(File Dependency)——當硬盤上的某個(某些)文件更改時,強制移除緩存數據;如:
CacheDependency cDependency = new
CacheDependency(Server.MapPath("authors.xml"));
Cache.Insert("CachedItem", item, cDependency);
·鍵值依賴(Key Dependency)——指定緩存中的某個數據項更改時移除。如:
// Create a cache entry.
Cache["key1"] = "Value 1";
// Make key2 dependent on key1.
String[] dependencyKey = new String[1];
dependencyKey[0] = "key1";
CacheDependency dependency = new CacheDependency(null, dependencyKey);
Cache.Insert("key2", "Value 2", dependency);
·基於時間的過時策略——按照預先定義的時間策略來使數據失效,能夠是絕對時間(如某個日期的18:00)也能夠是相對如今的相對時間。如:
/// Absolute expiration
Cache.Insert("CachedItem", item, null, DateTime.Now.AddSeconds(5),Cache.NoSlidingExpiration);
/// Sliding expiration
Cache.Insert("CachedItem", item, null, Cache.NoAbsoluteExpiration,
TimeSpan.FromSeconds(5));
使用過短和太長的過時時間都不行,不是形成用不上的緩存數據,就是緩存了陳舊的數據並加劇了緩存負擔,因此可使用高併發的測試來決定過時時間的最佳值。
·另外有個問題就是如何實現對數據庫的依賴,這就要求實現本身的通知機制,當數據庫數據改變時可以通知你的緩存數據改變。可參考http://www.gotdotnet.com/team/rhoward的示例。
因爲數據會過時,因此當使用緩存中的數據時,必須檢查數據的有效性。如如下代碼:
string data = (string)Cache["MyItem"];
if (data == null)
{
data = GetData();
Cache.Insert("MyItem", data);
}
DoSomeThingWithData(data);
依賴和過時策略指定了緩存中數據的移除方式,有時候你可能須要在移除發生時作一些工做,這能靠寫代碼來實現這一點,這就是咱們要講到的。
你能夠定義回調,這樣當移除自動發生時, 你能夠不移除它或者使用新的數據來替換它。如:
CacheItemRemovedCallback onRemove = new CacheItemRemovedCallback(this.RemovedCallback);
Cache.Insert("CachedItem",
item,
null,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.Default,
onRemove);
// Implement the function to handle the expiration of the cache.
public void RemovedCallback(string key, object value, CacheItemRemovedReason r)
{
// Test whether the item is expired, and reinsert it into the cache.
if (r == CacheItemRemovedReason.Expired)
{
// Reinsert it into the cache again.
CacheItemRemovedCallback onRemove = null;
onRemove = new CacheItemRemovedCallback(this.RemovedCallback);
Cache.Insert(key,
value,
null,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.Default,
onRemove);
}
}
當運行應用程序的服務器內存不足時,會自動清除緩存中的數據,稱爲「清除scavenging」。此時,Cache對象根據緩存項的優先級來決定先移除哪些緩存數據,你能夠在代碼中指定緩存項的優先級。參看MSDN中「CacheItemPriority 枚舉」,如:
Cache.Insert("DSN", connectionString, null, d, t, CacheItemPriority.High, onRemove);
沒有直接的方法來刷新Asp.net的輸出緩存,可是有替代方法(設置全部數據失效),好比:
Response.Cache.SetExpires(DateTime.Now)
這能夠清除緩存,但頁面上並不馬上體現出來,直到最初的緩存期結束,好比:
<%@ OutputCache Duration="10" VaryByParam="none" %>指令指定的緩存只會在10秒後才清除。一般並不須要清除全部緩存項,你只要從新加載數據更新緩存就夠了。
你可使用兩種方式的輸出緩存來緩存須要傳輸和顯示到客戶端瀏覽器上的數據——頁面輸出緩存(Page Output Cache)和頁面片段緩存(Page Fragment Cache)。當整個頁面相對變化較少時,能夠緩存整個頁面;若是隻是頁面的一部分常常變化,可使用片段緩存。
Page Output Caching將對頁面請求的響應放入緩存中,後續對此頁面的請求將直接從緩存中獲得信息而不是重建此頁面。能夠經過添加Page指令(高級別,聲明實現)來實現,也可使用HTTPCachePolicy類來實現(低級別,程序實現)。本指南不打算介紹技術細節,只給出如何更好使用的指南和最佳實踐。有四方面的內容:
一、決定緩存的內容
頁面輸出緩存可緩存各類信息,緩存這些信息意味着你不須要常常處理一樣的數據和結果,包括:
·常常被請求但不不改變的靜態頁面;
·更新頻率和時間已知的頁面(如顯示股票價格的頁面);
·根據HTTP參數,有幾個可能輸出的頁面(如根據城市的代號顯示該城市天氣狀況的頁面);
·從Web Service返回的結果;如:
[WebMethod(CacheDuration=60)]
public string HelloWorld()
{
return "Hello World";
}
二、緩存動態頁面
基於輸入參數、語言和瀏覽器類型改變的動態網頁常常用到。你可使用OutputCache的如下屬性來實現對動態頁面的緩存:
VaryByParam——基於輸入參數不一樣緩存同一頁面的多個版本;
VaryByHeader——基於Page Header的內容不一樣緩存頁面的多個版本;
VaryByCustom——經過聲明屬性和重載GetVaryByCustomString方法來定製緩存處理頁面的多個版本;
VaryByControl——基於控件中asp對象屬性的不一樣來緩存控件。
對多個版本頁面的緩存會下降可用內存,因此要仔細衡量緩存策略。s
三、控制緩存的位置
你可使用@OutputCache指令的OutputCacheLocation屬性的枚舉值來指定緩存的位置,如:
<%@ outputcache duration="10" varybyparam="none" Location="Server" %>
四、配置頁面輸出緩存
有兩種方式控制,你可使用Page指令,也可使用Cache API編程實現。參考如下兩段代碼:
//代碼1,使用指令
<%@ OutputCache Duration="20" Location="Server" VaryByParam="state" VaryByCustom="minorversion" VaryByHeader="Accept-Language"%>
//代碼2,編程實現
private void Page_Load(object sender, System.EventArgs e)
{
// Enable page output caching.
Response.Cache.SetCacheability(HttpCacheability.Server);
// Set the Duration parameter to 20 seconds.
Response.Cache.SetExpires(System.DateTime.Now.AddSeconds(20));
// Set the Header parameter.
Response.Cache.VaryByHeaders["Accept-Language"] = true;
// Set the cached parameter to 'state'.
Response.Cache.VaryByParams["state"] = true;
// Set the custom parameter to 'minorversion'.
Response.Cache.SetVaryByCustom("minorversion");
…
}
有時候緩存整個頁面並不靈活,同時內存的發但也比較大,這時候應考慮片段緩存。頁面片段緩存適合如下類型的數據:
·建立開銷很大的頁面片段(控件);
·包含靜態數據的頁面片段;
·可被多個用戶使用的頁面片段;
·多個頁面共享的頁面片段(如公用菜單條)
如下是緩存部分頁面的例子:
// Partial caching for 120 seconds
[System.Web.UI.PartialCaching(120)]
public class WebUserControl : System.Web.UI.UserControl
{
// Your Web control code
}
Asp.net Cache位於System.Web命名空間,但因爲它是一個通用的方案,因此仍然能夠在引用此命名空間的任何非Web項目中使用它。
System.Web.Caching.Cache 類是對象的緩存,它能夠經過System.Web.HttpRuntime.Cache 的靜態屬性或System.Web.UI.Page 和System.Web.HttpContext.Cache來訪問。所以在請求上下文以外也能夠存在,在每一個應用程序域中只有一個實例,因此HttpRuntime.Cache對象能夠在Aspnet_wp.exe以外的每一個應用程序域中存在。如下代碼演示了在普通應用裏訪問Cache對象:
HttpRuntime httpRT = new HttpRuntime();
Cache cache = HttpRuntime.Cache;
.Net Remoting提供了跨應用程序域、跨進程、跨計算機的程序運行框架。服務器激活的對象有兩種激活模式,其中Singleton類型任什麼時候候都不會同時具備多個實例。若是存在實例,全部客戶端請求都由該實例提供服務。若是不存在實例,服務器將建立一個實例,而全部後繼的客戶端請求都將由該實例來提供服務。因爲 Singleton類型具備關聯的默認生存期,即便任什麼時候候都不會有一個以上的可用實例,客戶端也不會總接收到對可遠程處理的類的同一實例的引用。因此將數據緩存起來能夠在多個客戶端之間共享狀態信息。
爲了使用.Net Remoting實現緩存方案,要保證遠程對象的租約不過時,而且遠程對象沒有被垃圾回收器銷燬(對象租約是指在系統刪除該對象前它在內存中的生存期)。當實現緩存時,重載MarshalByRefObject的InitializeLifetimeService方法而且返回null,這樣就能保證租約永遠不過時而且相關的對象生存期是無限的。如下代碼是一個示例:
public class DatasetStore : MarshalByRefObject
{
// A hash table-based data store
private Hashtable htStore = new Hashtable();
//Returns a null lifetime manager so that GC won't collect the object
public override object InitializeLifetimeService() { return null; }
// Your custom cache interface
}
注意:因爲這種方案的成本較高、性能上的限制而且可能形成系統不穩定,一般採用基於Sql Server的方案來替代。
內存映射文件提供獨一無二的特性,容許應用程序經過指針來訪問磁盤上的文件——與訪問動態內存趣的方式同樣。因此你能夠將應用程序進程中的某個地址段的數據映射到文件中,供多個跨應用程序域或跨進程訪問。
在windows中,代碼和數據是以以種方式處理的,表現形式都是內存頁,而在內存頁背後都是磁盤上的文件。惟一的不一樣磁盤上的文件類型不一樣。代碼後面是可執行的鏡像,而數據後面則是系統的頁面文件。當多個應用程序共享內存時,系統的性能會有明顯提高。
你可使用內存映射文件的這種特性來實現同一臺機器上的跨進程和跨應用程序域的緩存解決方案。基於內存映射文件的緩存方案包含如下組件:
·windows NT服務——啓動時建立內存映射文件,中止時刪除它。功能是向使用緩存的進程提供句柄。固然,也可使用命名的內存映射文件來提供操做接口;
·緩存託管組件(Cache Management Dll)——實現特定的緩存功能,好比:
a. 插入和刪除數據項到緩存中;
b. 使用算法清除緩存,好比最後使用算法(Least Recently Used);
c. 保證數據不被篡改;
基於內存映射文件的緩存方案能夠用在應用程序的每一個層中,但因爲使用win32 API調用,因此並不容易實現。.Net 框架不支持內存映射文件,因此只能以非託管代碼的方式運行,固然也不能利用.Net框架的有力特性,好比垃圾回收等。同時緩存數據項的管理功能須要定製開發,還要開發性能計數器來監控緩存的效果。
若是須要在進程回收(重啓)、機器重啓或電源故障的過程當中保持緩存數據的有效,基於內存的方案並不能知足要求。你可使用基於永久數據存儲的方案,如SQL server數據庫或NTFS文件系統。
SQL Server在使用sql語句或存儲過程獲得數據時,對varchar和varBinary類型的數據有8k的大小限制,你必須使用.Net 框架提供的Ado.Net SQLDataAdapter對象來訪問datatable或dataset。
使用SQL Server緩存數據的優勢:
·易於實現——使用.Net 框架和Ado.Net訪問數據庫至關方便;
·完善的安全模型和很高的健壯性;
·數據很是方便的共享;
·數據的持久保留。
·支持很大的數據量。
·方便的管理工具
固然,也有缺點:
·須要安裝SQL Server,對小型應用來講不合適;
·從新構造數據的性能和讀取數據庫的性能比較;
·網絡負擔。
靜態變量經常使用來記錄類的狀態,你能夠用它來建立定製的緩存對象。在定製的緩存類中將你的數據存儲器聲明爲靜態變量,而且提供維護接口(插入、刪除和訪問等)。若是沒有特殊的緩存需求(好比依賴、失效策略等),使用靜態變量緩存數據是很方便的。因爲是在內存中,這種方案可提供對緩存數據的直接、高速的訪問,當沒有替代方案解決鍵值對的存儲且對速度要求很高時,可使用靜態變量。固然,在asp.net中,應該使用Cache對象。
你可使用這種方案保存大數據的對象,前提是它不常常更改。因爲沒有清除機制,大數據的內存消耗會影響性能。
你須要保證定製線程安全機制,或者使用.Net框架提供的同步對象,好比Hashtable。如下代碼是使用Hashtable實現的例子:
static Hashtable mCacheData = new Hashtable();
應用範圍:本方案的應用範圍能夠限制到類、模塊或整個項目。若是變量定義爲public,整個項目中的代碼都能訪問它,範圍是整個應用程序域,實現了高效的共享。而它的生存期是和範圍緊密相關的。
你可使用基於HttpSessionState對象的asp.net session state來緩存單個用戶的會話狀態信息。它解決了asp中會話狀態的不少限制,包括:
·asp session要求客戶端接受cookies,不然就不能使用session;而asp.net能夠配置爲不使用cookie;
·對web server場的狀況,asp的session不能支持;當穩定性和可用性要求很高時,asp.net session state雖然效果很差,但對比較小的單個值scalar Value(好比登陸信息),仍是頗有效。
Asp.net session有很大改進,下面描述使用範圍和使用方式。
Asp.net session state有三種操做模式:
一、 進程內模式InProc——Session State信息在asp.net工做進程aspnet_wp.exe的進程的內存中存儲。這是默認選項,這種狀況下,若是進程或應用程序域被回收,則Session 狀態信息也被回收;
二、 進程外模式State Server——狀態信息序列化後保存在獨立的狀態進程中(AspNet_State.exe),因此狀態信息能夠保存在專門的服務器上(一個狀態服務器State Server);
三、 Sql server模式——狀態信息序列化後保存在SQL Server數據庫中。
你能夠經過調整配置文件中<sessionState>標籤的mode屬性來設置要使用的狀態模式,好比使用SQL Server模式來在Web server場中共享狀態信息。固然,這個優點也有缺點,就是狀態信息須要序列化和反序列化,同時多了對數據庫的寫入和讀取,因此性能上有開銷,這是要仔細評估的。
當使用進程內模式時,狀態信息保存在aspnet_wp.exe的進程中。因爲在web場的狀況下aspnet_wp.exe的多個實例在同一臺服務器上運行,因此進程內模式不適用與web場的狀況。
進程內模式是惟一支持Session_End事件的session模式,當用戶會話超時或停止時,能夠運行Session_End中的事件處理代碼來清除資源。
StateServer模式使用指定的進程儲存狀態信息。由於它也是一種進程外模式,因此要保證你存儲的對象是可序列化的,以支持跨進程傳輸。
當使用Session對象在web場的狀況下使用時,必須保證web.config文件中的<MachineKey>元素在全部服務器上是惟一的。這樣全部的服務器使用一樣的加密方式,才能訪問緩存中的數據。參考msdn中的「MachineKey元素」。
SQL Server模式下,當你使用信任鏈接(trusted_connection=true 或integrated security=sspi)訪問Session state信息時,不能在asp.net中使用身份用戶模擬。
默認狀況下,SQL Server將狀態信息存儲在TempDb數據庫中,它在每次Sql server服務啓動時會自動從新建立,固然,你能夠指定本身的數據庫以便在數據庫重啓的過程當中也能保持數據。
你可使用Session對象緩存任何類型的.net框架數據,可是要了解對某種類型來講最好的方式是什麼。有如下幾點須要說明:
一、 對基本類型(好比Int,Byte,String)來講,可使用任何方式。由於在選用進程外方式時,asp.net使用一個優化的內部方法來序列化和反序列化基本類型的數據;
二、 對複雜類型(如ArrayList)來講,只選用進程內方式。由於asp.net使用BinaryFormatter來序列化和反序列化這類數據,而這會影響性能的。固然,只有在State Server和SQL Server的方式下,纔會進行序列化操做;
三、 緩存的安全問題,當在緩存中存儲敏感數據時,須要考慮安全性,其它頁面能夠訪問到緩存中的數據;
四、 避免緩存大數據,那會下降性能;
五、 這種緩存方式不支持過時策略、清除和依賴。
Asp.net提供了簡單接口來操做Session State,並可以使用Web.Config進行簡單設置,當配置文件中的設置改變時,可以在頁面上馬上體現出來,而不須要從新啓動asp.net進程。
如下代碼演示了使用SQL Server來實現Session數據的存儲和使用。
<sessionState
mode="SQLServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1; Integrated Security=SSPI"
cookieless="false"
timeout="20"
/>
private void SaveSession(string CartID)
{
Session["ShoppingCartID"] = CartID;
}
private void CheckOut()
{
string CartID = (string)Session["ShoppingCartID"];
if(CartID != null)
{
// Transfer execution to payment page.
Server.Transfer("Payment.aspx");
}
else
{
// Display error message.
}
}
你還可使用客戶端存儲頁面信息的方式來下降服務器的負擔,這種方法提供最低的安全保障,但卻有最快的性能表現。因爲須要將數據發送到客戶端存儲,因此數據量有限。
實現客戶端緩存的機制有如下五種,接下來將依次介紹:
·隱藏欄位(Hidden Field)
·View State
·隱藏幀(Hidden Frame)
·Cookies
·Query String
這五種方式分別適合於存儲不一樣類型的數據。
你能夠將常常改變的少許數據保存在HtmlInputHidden中來維護頁面的狀態。當每次頁面回送的過程當中,這些數據都會包含在表單中大送到服務器,因此你要使用HTTP POST方式來提交頁面。
使用這種方式的優勢以下:
缺點:
示例:
<input id="HiddenValue" type="hidden" value="Initial Value" runat="server" NAME="HiddenValue">
全部的Web Form頁面和控件都包含有一個ViewState屬性,在對同一頁面屢次請求時能夠保持頁面內的值。它的內部實現是維護相應的hidden field,只不過是加密了的,因此比hidden field的安全性要好。
使用View State的性能表現很大程度上依賴於服務器控件的類型。通常來講,Label,TextBox,CheckBox,RadioButton,HyperLink的性能要好一些,而DropdownList,ListBox,DataGrid和DataList就要差不少,由於包含的數據量太大,因此每次頁面回送都很耗時間。
有些狀況下不推薦使用ViewState,好比:
一、 不須要回送的頁面避免使用;
二、 避免使用ViewState保存大數據量;
三、 在須要使用會話超時的狀況下避免使用它,由於它沒有超時操做。
ViewState的性能表現和Hidden Field的是相似的,可是具備更高的安全性。
優勢:
缺點:
示例代碼以下:
public class ViewStateSample : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
{
// Save some data in the ViewState property.
this.ViewState["EnterTime"] = DateTime.Now.ToString();
this.ViewState["UserName"] = "John Smith";
this.ViewState["Country"] = "USA";
}
}
…
private void btnRefresh_Click(object sender, System.EventArgs e)
{
// Get the saved data in the view state and display it.
this.lblTime.Text = this.ViewState["EnterTime"].ToString();
this.lblUserName.Text = this.ViewState["UserName"].ToString();
this.lblCountry.Text = this.ViewState["Country"].ToString();
}
}
你可使用Hidden Frame在客戶端緩存數據,這就避免了使用hidden field和使用view state時每次頁面回送時的緩存數據往返。好比你能夠祕密的加載多個頁面所須要的圖片,這並不會消耗服務器資源。
優勢:
a. 能夠加載較多數據而不僅是單個欄位的值;
b. 避免了沒必要要的屢次回送中的數據往來;
c. 能夠緩存和讀取在不一樣表單中存儲的數據項(能夠同時緩存多個頁面的數據);
d. 能夠訪問同一站點不一樣frame中的客戶端腳本數據。
缺點:
a. 有些瀏覽器不支持frame;
b. 源代碼能夠在客戶端看到,有潛在的安全威脅;
c. 隱藏frame的數量沒有限制,若是框架頁面包含較多hidden frame的話,在首次加載時速度會有限制。
示例代碼以下:
<FRAMESET cols="100%,*">
<FRAMESET rows="100%,*">
<FRAME src="contents_of_frame1.html">
</FRAMESET>
<FRAME src="contents_of_hidden_frame.html">
<FRAME src="contents_of_hidden_frame.html" frameborder="0" noresize scrolling="yes">
<NOFRAMES>
<P>This frameset document contains:
<A href="contents_of_frame1.html" TARGET="_top">Some neat contents</A>
</NOFRAMES>
</FRAMESET>
Cookie是能夠在客戶端存儲數據另外一種方案,這裏不過多介紹。
優勢:
缺點:
參看示例代碼:
public class CookiesSample : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
if (this.Request.Cookies["preferences1"] == null)
{
HttpCookie cookie = new HttpCookie("preferences1");
cookie.Values.Add("ForeColor","black");
cookie.Values.Add("BackColor","beige");
cookie.Values.Add("FontSize","8pt");
cookie.Values.Add("FontName","Verdana");
this.Response.AppendCookie(cookie);
}
}
private string getStyle(string key)
{
string val = null;
HttpCookie cookie= this.Request.Cookies["preferences1"];
if (cookie != null)
{
val = cookie.Values[key];
}
return val;
}
}
Query String是在用戶請求的URL後加上相應的參數來使用的,只能在使用HTTP GET方式調用URL時可用。
優勢:
d. 不須要服務器資源,參數附在URL裏面;
e. 應用面廣,幾乎全部瀏覽器都支持;
f. 實現簡單,服務端使用Request對象可直接讀取。
缺點:
a. 參數直接對用戶可見,不安全;
b. URL長度的限制,多數瀏覽器不支持超過255字符的URL。
示例代碼:
http://www.cache.com/login.asp?user=ronen
string user = Request.QueryString["User"];
下表是使用客戶端緩存的建議:
緩存機制 |
適用狀況 |
Hidden Field |
當安全性要求不高時,在頁面中存儲少許數據以提交到服務器上的本頁面或其它頁面。 |
ViewState |
在單個頁面中存儲少許信息知足頁面屢次回傳的要求。提供基本的安全機制。 |
Hidden Frame |
在客戶端存儲數據,避免了數據到服務器的回傳。 |
Cookie |
當安全性要求不高時,存儲少許數據在客戶端。 |
Query String |
當使用頁面地址鏈接頁面時傳輸少許參數。 |
IE提供了緩存機制,能夠實現對頁面的數據進行緩存,同時能夠指定過時時間。用戶在IE中請求此頁面,若是當過時時間沒有到,則自動從緩存中提取並呈現;不然,就到服務器上獲取新版本。IE對頁面的緩存能夠在IIS中設置。
適合在Internet Explorer中緩存的內容
優勢:
缺點:
示例代碼:
<META HTTP-EQUIV="expires" CONTENT="Tue, 23 Jun 2002 01:46:05 GMT">
本文檔介紹了緩存和狀態數據存儲的相關概念,以及可供使用的緩存技術,介紹了各類技術的適用範圍,並對其優缺點進行了說明,另外有簡單的性能比較和簡單的示例代碼。更多內容請參看相應的參考資料。