国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

ASP.NET 中 Session 實現原理淺析 [2] 狀態管理器

2024-07-10 12:56:57
字體:
來源:轉載
供稿:網友
狀態管理本來是一件很美好的事情,嘿嘿,只可惜總是有些廠商在實現的時候考慮得不那么周全。例如 ms 在 asp 中的狀態管理實現就比較爛,因為只實現了一個進程內的基于內存的狀態管理,故而存在很多問題:

1.所有的 session 數據都保存在 web 服務的進程中,會造成服務器支持會話數量受到服務器內存資源的限制問題,同時也因為大量非活動會話導致內存被無效占用。
2.服務器進程崩潰會導致所有的會話數據丟失。
3.會話無法跨進程或在負載均衡情況下使用,除非負載均衡技術保障同一用戶每次都能被路由到同一機器上。就算這樣也無法保障服務器崩潰造成的會話數據丟失。
4.需要 cookie 的支持,而現在因為安全性問題,很多人在瀏覽器中關閉了 cookie 和 js 的支持。

為此 asp 的使用者不得不自己手工將會話信息以會話 id 為主鍵同步到外部數據庫中,以緩解類似問題。

而在 asp.net 中,因為設計時就考慮了這些問題,能夠避免這些限制:

1.支持進程外的狀態管理,通過獨立狀態管理服務或 sql server 狀態服務器管理會話狀態
2.支持不使用 cookie 的狀態維護,通過在 url 中自動增加會話 id 來避免使用 cookie
3.通過獨立的狀態管理服務或sql server 狀態服務器支持負載均衡時同步使用會話信息

實現這些特性的正是上節提到的 sessionstatemodule.initmodulefromconfig 函數中,根據 sessionstate 標記的 mode 屬性選擇的四種不同的狀態管理器實現。


以下內容為程序代碼:

<system.web>
<sessionstate mode="inproc"
stateconnectionstring="tcpip=127.0.0.1:42424"
statenetworktimeout="10"
sqlconnectionstring="data source=127.0.0.1;integrated security=sspi"
cookieless="false"
timeout="20" />
</system.web>



off 模式禁止會話管理,同時 asp.net 還允許通過在頁面中以 enablesessionstate 屬性細粒度管理頁面的會話支持狀態
以下內容為程序代碼:

<%@ page enablesessionstate=" true|false|readonly" %>



inproc 模式兼容以前 asp 的策略,在 asp.net 同一進程空間內實現基于內存的會話狀態管理,速度最快但受到與 asp 相同的限制;
stateserver 模式通過 asp.net 獨立安裝的 asp.net state service 服務(aspnet_state.exe),以 stateconnectionstring 指定的ip和端口響應會話狀態服務;
sqlserver 模式則通過 sqlconnectionstring 指定的 sql server 服務器,以內存臨時表(以 installsqlstate.sql建庫,使用 tempdb 內存數據庫)或獨立表(以installpersistsqlstate.sql 監控,使用獨立的 aspstate 庫)維護會話狀態。

這四種不同的狀態管理器,在性能上據《performance tuning and optimizing asp.net appliation》一書的測試,相對值如下:

以下為引用:

table 4-1: normalized ttlb(time to last byte) by session state mode (in milliseconds per 100 requests)

concurrent browsers mode = off mode = inproc mode = stateserver mode = sqlserver
1 7.81 4.54 8.27 8.47
5 28.28 20.25 27.25 29.29
10 89.38 46.08 77.29 85.11


table 4-2: average requests per second by session state mode

concurrent browsers mode = off mode = inproc mode = stateserver mode = sqlserver

1 18.86 24.17 18.31 18.11
5 21.66 25.74 21.54 21.34
10 17.23 23.8 18.11 17.6




可以看到,無論是從 ttlb 還是每秒平均請求數來說,進程外狀態管理器的性能都是可以令人接受的,當然還需要針對狀態管理情況在編寫代碼時做相關優化。不過要使用進程外狀態管理器,則保存在會話中的對象受到必須提高二進制序列化支持的限制。

從使用角度來看,狀態管理器實際上都是由上節提到的 httpsessionmodule 建立管理,并通過 httpsessionstate 接口提供訪問的,結構如下圖:


msdn 上的 underpinnings of the session state implementation in asp.net 一文非常詳細的解釋了幾種不同狀態管理器的原理和使用,這兒就不羅嗦了。

從實現角度來看,上節中提到的 sessionstatemodule.initmodulefromconfig 函數,根據配置文件中狀態管理器的模式,分別建立 system.web.sessionstate.inprocstateclientmanager, system.web.sessionstate.outofprocstateclientmanager 和 system.web.sessionstate.sqlstateclientmanager 三類狀態管理器的實例。他們都繼承自 system.web.sessionstate.stateclientmanager 抽象基類,并通過 system.web.sessionstate.istateclientmanager 接口向 httpapplication 提高狀態管理服務。

istateclientmanager 接口是狀態管理器的統一管理接口,主要提供以下功能:
以下內容為程序代碼:

internal interface system.web.sessionstate.istateclientmanager.istateclientmanager
{
// 配置管理狀態管理器
void configinit(sessionstatesectionhandler.config config, sessiononendtarget onendtarget);
// 保存 sessionstatemodule 實例供后面使用
void setstatemodule(sessionstatemodule module);
void resettimeout(string id);
void dispose();

void set(string id, sessionstateitem item, bool instorage);

// 維護狀態管理器內容
iasyncresult beginget(string id, asynccallback cb, object state);
sessionstateitem endget(iasyncresult ar);

iasyncresult begingetexclusive(string id, asynccallback cb, object state);
sessionstateitem endgetexclusive(iasyncresult ar);
void releaseexclusive(string id, int lockcookie);
}



configinit 方法主要在初始化狀態管理器時通知其根據配置進行初始化工作,并將負責會話狀態清除的 sessiononendtarget 對象實例綁定到會話管理器(我們后面討論會話狀態管理實現時詳細討論)。對 outofprocstateclientmanager 和 sqlstateclientmanager 來說,在此階段還會初始化與外部服務器的連接,并通過一個 system.web.util.resourcepool 實例,提供基于時間策略的資源池來維護連接;
resettimeout 方法重置指定 session 的超時時間;對 inprocstateclientmanager 來說,這個超時時間是通過 system.web.caching.cacheinternal 類型實現的緩存對象來使用的; outofprocstateclientmanager 直接通過 makerequest 函數構造請求發給外部獨立的狀態管理器執行; sqlstateclientmanager 則調用存儲過程 tempresettimeout 更新 aspstatetempsessions 表的過期時間 expires 字段;
dispose 方法是否狀態管理器的資源,落實到代碼就是對 outofprocstateclientmanager 和 sqlstateclientmanager 中資源池的釋放;

set 方法則將指定的 sessionstateitem 存儲到 id 相關的會話數據中,并根據 instorage 指定的對象狀態,決定在發生異常的情況下是否釋放對此會話的鎖。與 resettimeout 的實現類似,outofprocstateclientmanager 發送請求給外部獨立的狀態管理器;sqlstateclientmanager 調用存儲過程 tempupdatestateitemxxx 更新會話狀態表 aspstatetempsessions 中的過期時間 expires 字段、鎖定狀態 lock 字段、以及狀態信息 sessionitemshort/sessionitemlong (分別保存7000字節以下或之上的數據)。如發生異常并設置 instorage 標記,則先調用 tempreleasestateitemexclusive 釋放會話鎖。

對狀態管理器中數據的獲取較為復雜,istateclientmanager 接口使用的是異步調用的模式,并為提高效率將獨占的獲取數據單獨拿出來。狀態管理器實現類通過通用基類 system.web.sessionstate.stateclientmanager 實現的幾個工具方法,將數據獲取操作異步化。再最終由實現類通過 get 和 getexclusive 方法完成操作。獲取數據的方法 inprocstateclientmanager 通過緩存;outofprocstateclientmanager 通過請求;sqlstateclientmanager 通過 tempgetstateitemxxx 存儲過程完成。

在了解了 sessionstatemodule 控制的狀態服務器的實現和使用方法后,我們來看看上層的 httpsessionstate 是如何使用的。



mandeep s bhatia 的 asp.net session management internals 介紹了 httpsessionstate 內部完成狀態信息管理的原理。httpsessionstate 的 item 屬性實際上是通過 sessiondictionary 實例實現的。
以下內容為程序代碼:

public sealed class httpsessionstate : ...
{
private sessiondictionary _dict;

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



而此 sessiondictionary 實例與 httpsessionstate 實例的構造,都是在前面提到的完成會話構造的 sessionstatemodule.completeacquirestate 方法中完成的:
以下內容為程序代碼:

public sealed class sessionstatemodule : ihttpmodule
{
private string _rqid;
private sessiondictionary _rqdict;
private httpstaticobjectscollection _rqstaticobjects; // 靜態對象,通過頁面中 <object runat="server" scope="session"/> 標記設置
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);

}
}



這兒涉及到的幾個字段,基本上都能跟 httpsessionstate 提供的公共屬性對應起來。需要注意的是 httpsessionstate.staticobjects 是通過 asp.net 頁面上的 <object runat="server" scope="session"/> 類似標記靜態定義的;_rqreadonly 則是前面提到的 <%@ page enablesessionstate=" readonly" %> 標記設置的。

至此,狀態管理器的使用與實現方法基本上分析完成,下面整理一下其使用流程:

1.構造:httpapplication 在初始化過程中調用 initmodules 初始化配置文件 machine.config 中注冊的實現了 ihttpmodule 接口的 http 模塊;其中 sessionstatemodule 作為模塊之一被構造并初始化;其 initmodulefromconfig 方法根據配置文件中狀態管理器的相關配置,構造并初始化相應的狀態管理器;并根據各種條件調用 completeacquirestate 方法完成 httpsessionstate 的構造工作。
2.使用:httpsessionstate 通過 sessiondictionary 實現其 item 屬性的狀態數據管理;sessiondictionary 本身由 sessionstatemodule.onreleasestate 在適當的時候寫回狀態管理器;其他維護操作也是通過 sessionstatemodule 調用狀態管理器的 istateclientmanager 接口完成的。
3.實現:狀態管理器從抽象基類 stateclientmanager 獲得異步調用的封裝;通過 istateclientmanager 接口提供給 sessionstatemodule 管理其初始化、釋放和管理的接口。

雖然 asp.net 做了很多工作,但個人感覺還遠遠不夠。例如 inproc/outofproc 實際上都是在內存中,只是解決了一個可靠性和數據集中同步的問題;sql server 雖然能夠解決容量、可靠性和數據集中同步的問題,但效率又受到影響。這方面 .net 應該向 java 好好學習一下,例如 java 下 ehcache 和 oscache 都提供了平滑的可配置二級(內存/硬盤)緩存介質切換,并且后者還提供了對負載均衡的簡單支持,此外還有 jboss 等實現的基于 ip 多播等實現技術的負載均衡緩存實現等等,都遠遠超出了 asp.net 提供的緩存機制所考慮到的范圍。雖然 asp.net 也有獨立的緩存機制,ms 也提出了 cache application block 的參考實現,不過還是任重而道遠啊,呵呵



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新疆| 秦安县| 玉门市| 无锡市| 句容市| 宣武区| 伊宁县| 龙山县| 揭西县| 永平县| 崇义县| 南丰县| 福鼎市| 抚远县| 巩义市| 红桥区| 申扎县| 达日县| 墨脱县| 遂平县| 沁阳市| 丰原市| 宝兴县| 高密市| 华安县| 宣恩县| 隆安县| 济源市| 西吉县| 新巴尔虎右旗| 龙山县| 修文县| 安达市| 南皮县| 莱州市| 洛扎县| 马边| 台南县| 中牟县| 衡山县| 靖西县|