2013-09-27 71 views
6

我正在實施會話結構。如何處理打開的會話

我有一個ConcurrentDictionary在服務器端持有所有<SessionId, UserSession>對。

建立新連接時,根據RememberMe選項將cookie分配給客戶端瀏覽器,perm或temp。

當客戶端調用LogOut函數時,它會從字典中刪除會話。

但是,當客戶端瀏覽器簡單地關閉或崩潰,並且cookie丟失或過期或被刪除時,內存中的服務器端會話對象仍保留在字典中併成爲重影。隨着時間的推移,這些鬼魂會堆積起來。

我的問題是,如何改進設計,以便在死亡會話過期後可以清理?

我想過讓定時器服務運行一個清潔計劃,但感覺不夠優雅。有沒有更簡單的方法來做到這一點,而不依賴於外部服務?

+1

最好是使用帶滾動條件的緩存或處理Session_End方法。你在UserSession中存儲什麼? – zimdanen

+0

沒有可靠的Session_End方法來處理,如果客戶端瀏覽器崩潰,那麼它就在那裏結束,而不會回話到服務器。但現在你提到了一個緩存,我有一個想法,我可以存儲一個按LastActive時間排序的列表。每當新客戶端登錄時,他可以幫助檢查隊列中最早的會話,並在過期時刪除。當他呼叫服務器執行某些操作時,每個活動用戶都會將自己置於隊列的後面。所以,他成爲最新的活躍人物。 – Tom

+0

您是否在某些時候需要查看有關已登錄的每個人的數據?如果沒有,爲什麼不將數據存儲在會話中(如果您需要數據)並在會話超時後讓它消失?如果存在壓力,那麼也可以通過將項目從Session中刪除來處理內存壓力。或者使用帶滾動超時的HttpContext.Cache,以便在上次訪問後的一段時間後消失。 (基本上,不需要推出自己的產品。) – zimdanen

回答

4

我在我的一個項目中有類似的情況。

,而不是字典,我使用的緩存與用戶短絕對過期和會話ID作爲我的緩存鍵:

HttpContext.Current.Cache.Insert(sessionID, userEntity, null, DateTime.Now.AddSeconds(30), TimeSpan.Zero); 

,並在客戶端,我讓Ajax調用,每15秒,以通知服務器併爲該會話ID更新緩存。

因此,無論何時用戶關閉瀏覽器窗口,服務器都不會收到任何通知,並且用戶的會話ID自動過期。

+0

謝謝,在這個想法之後做了一些搜索,發現上面的.NET4中的System.Runtime.Caching似乎是要走的路。 http://bartwullems.blogspot.com.au/2011/02/caching-in-net-4.html – Tom

0

我幾個月後回答我自己的問題。如果我想要這樣的結構,我會使用Microsoft SignalR。因爲它以實時方式爲我控制會話並做更多事情。

+0

爲什麼你仍然在使用Sessions來認證用戶。這種方法是經典ASP時代的可行解決方案,但現在已經不存在了。您應該考慮使用「ASP.NET表單身份驗證」,而不是ASP中的首選方法。NET世界。 – VahidN

2

如果你的sessionstate是「InProc」,爲什麼不把你的代碼應用到Session_Start和Session_End?

void Session_Start(object sender, EventArgs e) 
{ 
    //Add to ConcurrentDictionary 
} 

void Session_End(object sender, EventArgs e) 
{ 
    // Note: The Session_End event is raised only when the sessionstate mode 
    // is set to InProc in the Web.config file. If session mode is set to StateServer 
    // or SQLServer, the event is not raised. 

    //Remove from ConcurrentDictionary 
}