黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

ASP.NET 中 Session 實(shí)現(xiàn)原理淺析 [2] 狀態(tài)管理

系統(tǒng) 3622 0

狀態(tài)管理本來是一件很美好的事情,嘿嘿,只可惜總是有些廠商在實(shí)現(xiàn)的時(shí)候考慮得不那么周全。例如MS在ASP中的狀態(tài)管理實(shí)現(xiàn)就比較爛,因?yàn)橹粚?shí)現(xiàn)了一個(gè)進(jìn)程內(nèi)的基于內(nèi)存的狀態(tài)管理,故而存在很多問題:

1.所有的Session數(shù)據(jù)都保存在Web服務(wù)的進(jìn)程中,會(huì)造成服務(wù)器支持會(huì)話數(shù)量受到服務(wù)器內(nèi)存資源的限制問題,同時(shí)也因?yàn)榇罅糠腔顒?dòng)會(huì)話導(dǎo)致內(nèi)存被無效占用。
2.服務(wù)器進(jìn)程崩潰會(huì)導(dǎo)致所有的會(huì)話數(shù)據(jù)丟失。
3.會(huì)話無法跨進(jìn)程或在負(fù)載均衡情況下使用,除非負(fù)載均衡技術(shù)保障同一用戶每次都能被路由到同一機(jī)器上。就算這樣也無法保障服務(wù)器崩潰造成的會(huì)話數(shù)據(jù)丟失。
4.需要Cookie的支持,而現(xiàn)在因?yàn)榘踩詥栴},很多人在瀏覽器中關(guān)閉了Cookie和js的支持。

為此ASP的使用者不得不自己手工將會(huì)話信息以會(huì)話ID為主鍵同步到外部數(shù)據(jù)庫中,以緩解類似問題。

而在ASP.NET中,因?yàn)樵O(shè)計(jì)時(shí)就考慮了這些問題,能夠避免這些限制:

1.支持進(jìn)程外的狀態(tài)管理,通過獨(dú)立狀態(tài)管理服務(wù)或SQLServer狀態(tài)服務(wù)器管理會(huì)話狀態(tài)
2.支持不使用Cookie的狀態(tài)維護(hù),通過在URL中自動(dòng)增加會(huì)話ID來避免使用Cookie
3.通過獨(dú)立的狀態(tài)管理服務(wù)或SQLServer狀態(tài)服務(wù)器支持負(fù)載均衡時(shí)同步使用會(huì)話信息

實(shí)現(xiàn)這些特性的正是上節(jié)提到的 SessionStateModule .InitModuleFromConfig函數(shù)中,根據(jù) sessionState 標(biāo)記的mode屬性選擇的四種不同的狀態(tài)管理器實(shí)現(xiàn)。
< system .web >
< sessionState mode ="InProc"
stateConnectionString
="tcpip=127.0.0.1:42424"
stateNetworkTimeout
="10"
sqlConnectionString
="datasource=127.0.0.1;IntegratedSecurity=SSPI"
cookieless
="false"
timeout
="20" />
</ system.web >

Off模式禁止會(huì)話管理,同時(shí)ASP.NET還允許通過在頁面中以EnableSessionState屬性細(xì)粒度管理頁面的會(huì)話支持狀態(tài)
<% @PageEnableSessionState = " True|False|ReadOnly " %>

InProc模式兼容以前ASP的策略,在ASP.NET同一進(jìn)程空間內(nèi)實(shí)現(xiàn)基于內(nèi)存的會(huì)話狀態(tài)管理,速度最快但受到與ASP相同的限制;
StateServer模式通過ASP.NET獨(dú)立安裝的ASP.NETStateService服務(wù)(aspnet_state.exe),以stateConnectionString指定的IP和端口響應(yīng)會(huì)話狀態(tài)服務(wù);
SQLServer模式則通過sqlConnectionString指定的SQLServer服務(wù)器,以內(nèi)存臨時(shí)表(以InstallSqlState.sql建庫,使用tempdb內(nèi)存數(shù)據(jù)庫)或獨(dú)立表(以InstallPersistSqlState.sql監(jiān)控,使用獨(dú)立的ASPState庫)維護(hù)會(huì)話狀態(tài)。

這四種不同的狀態(tài)管理器,在性能上據(jù)《PerformanceTuningandOptimizingASP.NETAppliation》一書的測(cè)試,相對(duì)值如下:
以下為引用:

Table4-1:NormalizedTTLB(TimetoLastByte)bySessionStateMode(inMillisecondsper100Requests)

CONCURRENTBROWSERSMODE=OFFMODE=INPROCMODE=STATESERVERMODE=SQLSERVER
17.814.548.278.47
528.2820.2527.2529.29
1089.3846.0877.2985.11


Table4-2:AverageRequestsperSecondbySessionStateMode

CONCURRENTBROWSERSMODE=OFFMODE=INPROCMODE=STATESERVERMODE=SQLSERVER

118.8624.1718.3118.11
521.6625.7421.5421.34
1017.2323.818.1117.6


可以看到,無論是從TTLB還是每秒平均請(qǐng)求數(shù)來說,進(jìn)程外狀態(tài)管理器的性能都是可以令人接受的,當(dāng)然還需要針對(duì)狀態(tài)管理情況在編寫代碼時(shí)做相關(guān)優(yōu)化。不過要使用進(jìn)程外狀態(tài)管理器,則保存在會(huì)話中的對(duì)象受到必須提高二進(jìn)制序列化支持的限制。

從使用角度來看,狀態(tài)管理器實(shí)際上都是由上節(jié)提到的HttpSessionModule建立管理,并通過HttpSessionState接口提供訪問的,結(jié)構(gòu)如下圖:


MSDN上的 UnderpinningsoftheSessionStateImplementationinASP.NET 一文非常詳細(xì)的解釋了幾種不同狀態(tài)管理器的原理和使用,這兒就不羅嗦了。

從實(shí)現(xiàn)角度來看,上節(jié)中提到的 SessionStateModule .InitModuleFromConfig函數(shù),根據(jù)配置文件中狀態(tài)管理器的模式,分別建立System.Web.SessionState.InProcStateClientManager,System.Web.SessionState.OutOfProcStateClientManager和System.Web.SessionState.SqlStateClientManager三類狀態(tài)管理器的實(shí)例。他們都繼承自System.Web.SessionState.StateClientManager抽象基類,并通過System.Web.SessionState.IStateClientManager接口向HttpApplication提高狀態(tài)管理服務(wù)。

IStateClientManager接口是狀態(tài)管理器的統(tǒng)一管理接口,主要提供以下功能:
internal interface System.Web.SessionState.IStateClientManager.IStateClientManager
{
// 配置管理狀態(tài)管理器
void ConfigInit(SessionStateSectionHandler.Configconfig,SessionOnEndTargetonEndTarget);
// 保存SessionStateModule實(shí)例供后面使用
void SetStateModule(SessionStateModulemodule);
void ResetTimeout( string id);
void Dispose();

void Set( string id,SessionStateItemitem, bool inStorage);

// 維護(hù)狀態(tài)管理器內(nèi)容
IAsyncResultBeginGet( string id,AsyncCallbackcb, object state);
SessionStateItemEndGet(IAsyncResultar);

IAsyncResultBeginGetExclusive(
string id,AsyncCallbackcb, object state);
SessionStateItemEndGetExclusive(IAsyncResultar);
void ReleaseExclusive( string id, int lockCookie);
}

ConfigInit方法主要在初始化狀態(tài)管理器時(shí)通知其根據(jù)配置進(jìn)行初始化工作,并將負(fù)責(zé)會(huì)話狀態(tài)清除的SessionOnEndTarget對(duì)象實(shí)例綁定到會(huì)話管理器(我們后面討論會(huì)話狀態(tài)管理實(shí)現(xiàn)時(shí)詳細(xì)討論)。對(duì)OutOfProcStateClientManager和SqlStateClientManager來說,在此階段還會(huì)初始化與外部服務(wù)器的連接,并通過一個(gè)System.Web.Util.ResourcePool實(shí)例,提供基于時(shí)間策略的資源池來維護(hù)連接;
ResetTimeout方法重置指定Session的超時(shí)時(shí)間;對(duì)InProcStateClientManager來說,這個(gè)超時(shí)時(shí)間是通過System.Web.Caching.CacheInternal類型實(shí)現(xiàn)的緩存對(duì)象來使用的;OutOfProcStateClientManager直接通過MakeRequest函數(shù)構(gòu)造請(qǐng)求發(fā)給外部獨(dú)立的狀態(tài)管理器執(zhí)行;SqlStateClientManager則調(diào)用存儲(chǔ)過程TempResetTimeout更新ASPStateTempSessions表的過期時(shí)間Expires字段;
Dispose方法是否狀態(tài)管理器的資源,落實(shí)到代碼就是對(duì)OutOfProcStateClientManager和SqlStateClientManager中資源池的釋放;

Set方法則將指定的SessionStateItem存儲(chǔ)到id相關(guān)的會(huì)話數(shù)據(jù)中,并根據(jù)inStorage指定的對(duì)象狀態(tài),決定在發(fā)生異常的情況下是否釋放對(duì)此會(huì)話的鎖。與ResetTimeout的實(shí)現(xiàn)類似,OutOfProcStateClientManager發(fā)送請(qǐng)求給外部獨(dú)立的狀態(tài)管理器;SqlStateClientManager調(diào)用存儲(chǔ)過程TempUpdateStateItemXXX更新會(huì)話狀態(tài)表ASPStateTempSessions中的過期時(shí)間Expires字段、鎖定狀態(tài)Lock字段、以及狀態(tài)信息SessionItemShort/SessionItemLong(分別保存7000字節(jié)以下或之上的數(shù)據(jù))。如發(fā)生異常并設(shè)置inStorage標(biāo)記,則先調(diào)用TempReleaseStateItemExclusive釋放會(huì)話鎖。

對(duì)狀態(tài)管理器中數(shù)據(jù)的獲取較為復(fù)雜,IStateClientManager接口使用的是異步調(diào)用的模式,并為提高效率將獨(dú)占的獲取數(shù)據(jù)單獨(dú)拿出來。狀態(tài)管理器實(shí)現(xiàn)類通過通用基類System.Web.SessionState.StateClientManager實(shí)現(xiàn)的幾個(gè)工具方法,將數(shù)據(jù)獲取操作異步化。再最終由實(shí)現(xiàn)類通過Get和GetExclusive方法完成操作。獲取數(shù)據(jù)的方法InProcStateClientManager通過緩存;OutOfProcStateClientManager通過請(qǐng)求;SqlStateClientManager通過TempGetStateItemXXX存儲(chǔ)過程完成。

在了解了 SessionStateModule 控制的狀態(tài)服務(wù)器的實(shí)現(xiàn)和使用方法后,我們來看看上層的HttpSessionState是如何使用的。



MandeepSBhatia的 ASP.NETSessionManagementInternals 介紹了HttpSessionState內(nèi)部完成狀態(tài)信息管理的原理。HttpSessionState的Item屬性實(shí)際上是通過SessionDictionary實(shí)例實(shí)現(xiàn)的。
public sealed class HttpSessionState:
{
private SessionDictionary_dict;

public object this [ string name]
{
get
{
return _dict[name];
}

set
{
_dict[name]
= value;
}

}

}

而此SessionDictionary實(shí)例與HttpSessionState實(shí)例的構(gòu)造,都是在前面提到的完成會(huì)話構(gòu)造的 SessionStateModule .CompleteAcquireState方法中完成的:

public sealed class SessionStateModule:IHttpModule
{
private string _rqId;
private SessionDictionary_rqDict;
private HttpStaticObjectsCollection_rqStaticObjects; // 靜態(tài)對(duì)象,通過頁面中<objectRunat="Server"Scope="Session"/>標(biāo)記設(shè)置
private int _rqTimeout;
private bool _rqIsNewSession;
private bool _rqReadonly;
private HttpContext_rqContext;
private SessionStateItem_rqItem;

private void CompleteAcquireState()
{
if (_rqItem != null )
{
if (_rqItem.dict != null )
{
_rqDict
= _rqItem.dict;
}

else
{
_rqDict
= new SessionDictionary();
}

_rqStaticObjects
= ((_rqItem.staticObjects != null ) ? _rqItem.staticObjects:
_rqContext.Application.SessionStaticObjects.Clone());
_rqTimeout
= _rqItem.timeout;
_rqIsNewSession
= false ;
_rqInStorage
= true ;
_rqStreamLength
= _rqItem.streamLength;
}

else
{
_rqDict
= new SessionDictionary();
_rqStaticObjects
= _rqContext.Application.SessionStaticObjects.Clone();
_rqTimeout
= SessionStateModule.s_config._timeout;
_rqIsNewSession
= true ;
_rqInStorage
= false ;
}

_rqDict.Dirty
= false ;

_rqSessionState
= new HttpSessionState(_rqId,_rqDict,_rqStaticObjects,_rqTimeout,_rqIsNewSession,
SessionStateModule.s_config._isCookieless,SessionStateModule.s_config._mode,_rqReadonly);

_rqContext.Items.Add(
" AspSession " ,_rqSessionState);

}

}


這兒涉及到的幾個(gè)字段,基本上都能跟HttpSessionState提供的公共屬性對(duì)應(yīng)起來。需要注意的是HttpSessionState.StaticObjects是通過ASP.NET頁面上的<objectRunat="Server"Scope="Session"/>類似標(biāo)記靜態(tài)定義的;_rqReadonly則是前面提到的<%@PageEnableSessionState="ReadOnly"%>標(biāo)記設(shè)置的。

至此,狀態(tài)管理器的使用與實(shí)現(xiàn)方法基本上分析完成,下面整理一下其使用流程:

1.構(gòu)造:HttpApplication在初始化過程中調(diào)用InitModules初始化配置文件Machine.config中注冊(cè)的實(shí)現(xiàn)了IHttpModule接口的HTTP模塊;其中 SessionStateModule 作為模塊之一被構(gòu)造并初始化;其InitModuleFromConfig方法根據(jù)配置文件中狀態(tài)管理器的相關(guān)配置,構(gòu)造并初始化相應(yīng)的狀態(tài)管理器;并根據(jù)各種條件調(diào)用CompleteAcquireState方法完成HttpSessionState的構(gòu)造工作。
2.使用:HttpSessionState通過SessionDictionary實(shí)現(xiàn)其Item屬性的狀態(tài)數(shù)據(jù)管理;SessionDictionary本身由 SessionStateModule .OnReleaseState在適當(dāng)?shù)臅r(shí)候?qū)懟貭顟B(tài)管理器;其他維護(hù)操作也是通過 SessionStateModule 調(diào)用狀態(tài)管理器的IStateClientManager接口完成的。
3.實(shí)現(xiàn):狀態(tài)管理器從抽象基類StateClientManager獲得異步調(diào)用的封裝;通過IStateClientManager接口提供給 SessionStateModule 管理其初始化、釋放和管理的接口。

雖然ASP.NET做了很多工作,但個(gè)人感覺還遠(yuǎn)遠(yuǎn)不夠。例如InProc/OutOfProc實(shí)際上都是在內(nèi)存中,只是解決了一個(gè)可靠性和數(shù)據(jù)集中同步的問題;SQLServer雖然能夠解決容量、可靠性和數(shù)據(jù)集中同步的問題,但效率又受到影響。這方面.NET應(yīng)該向Java好好學(xué)習(xí)一下,例如Java下 EHCache OSCache 都提供了平滑的可配置二級(jí)(內(nèi)存/硬盤)緩存介質(zhì)切換,并且后者還提供了對(duì)負(fù)載均衡的簡(jiǎn)單支持,此外還有JBoss等實(shí)現(xiàn)的基于IP多播等實(shí)現(xiàn)技術(shù)的負(fù)載均衡緩存實(shí)現(xiàn)等等,都遠(yuǎn)遠(yuǎn)超出了ASP.NET提供的緩存機(jī)制所考慮到的范圍。雖然ASP.NET也有獨(dú)立的緩存機(jī)制,MS也提出了CacheApplicationBlock的參考實(shí)現(xiàn),不過還是任重而道遠(yuǎn)啊,呵呵

ASP.NET 中 Session 實(shí)現(xiàn)原理淺析 [2] 狀態(tài)管理器


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論