2013-09-27 27 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 
}