您的位置:首页 > 其它

一个web应用程序统计在线用户列表的东东

2007-11-05 22:25 501 查看
来源:键盘敲击者cncxz http://olu.desktopit.net/whitepaper.aspx

一般来说,用户离开系统的方式有四种:主动注销、会话超时、直接关闭浏览器、在当前窗口导航到其他页面,对于前两种(正常退出),我们很容易便可将该用户从在线列表中清除;而后两种(非正常退出),由于无法捕获退出事件的精确时间,只能等到会话超时后才能将该用户清除出在线列表。假设我们设置会话超时时间为60分钟,则必须在1小时后才能将非正常退出的用户从在线列表中清除,而在实际应用中,有相当一大批的用户都习惯于非正常退出,所以采用普通方式维护的在线用户列表的时效性可想而知~~

  针对这种情况,2007年十一的时候做了一套解决方案,现在把它整理了一下发布出来,感觉可行的拿去研究一下吧。

  在线用户模块(OnlineUserBlock)的简要介绍
  主要功能特点
  即时有效地提供一份在线用户列表

   本模块是将这种尴尬降至最低的一个尝试。
  在线用户包含会员、访客两种

  实际应用中,站点应该还有许多访客,严格来说他们也算用户的一种(匿名用户),因而本模块的在线用户包含会员(普通用户)、访客(匿名用户)两种。

  控制会员帐号不能在多处同时登陆

  很多web系统(尤其是收费系统)非常厌恶多人共享同一帐号,本模块设置了一个控制开关,开启后会员帐号将禁止在多处同时登陆(要是俩人一个白天一个晚上分时段共享也是没有办法的),先登陆的将被后登陆的挤掉。



[b]在线用户模块(OnlineUserBlock)解决方案的实现思路

[/b]

核心功能的实现

在线用户列表时效性改进方案
为在线用户实体增设一个RefreshTime属性,在web系统的标志性页面(也可以是所有页面)上添加一个实现了System.Web.UI.ICallbackEventHandler接口的web控件, 该控件自页面加载成功开始利用javascript脚本无刷新循环调用(周期可配置)一个将当前用户的RefreshTime属性设置为当前时间的服务器端方法, 如果用户离开了所有包含此自动刷新控件的页面,那么RefreshTime属性便不会自动更新了。与此同时,我们在服务器端设置一个计时器,循环判断(周期可配置)在线列表中所有用户的RefreshTime属性, 自动清除那些超过特定时间(可配置,比客户端自动刷新周期长,远小于会话超时时间)不更新RefreshTime属性的用户。 当然,频繁的刷新会增大系统服务器负担,所以我们应该在服务器负担&在线用户列表时效性之间取一个均衡点,设置上文提到的三个参数。

将匿名用户(访客)加入在线名单
在ASP.NET2.0设置架构中新增加了一个anonymousIdentification元素(具体请参考msdn),设置其enabled 属性值为true可为当前应用程序启用匿名标识,之后调用HttpContext.Current.Request.AnonymousID可获取一个Guid转换而来的字符串, 使用这个字符串作为唯一标识创建普通用户(会员)&匿名用户(访客)的通用实体,在线用户列表即是对这一通用实体集合的维护。

禁止会员同时在多处登陆
这个功能的实现主要用两种途径:①某帐号一旦成功登陆后,在退出前不允许再次登陆;②登陆时判断此前是否有人用当前帐号登陆,若有则将其踢出。 对于第一种途径,由于非正常退出现象的存在,将有可能造成用户在某一特定时间内无法正常登陆,因而此处采用第二种途径。

在线列表的维护
下图(图一)描述了如何处理对 ASP.NET 资源的请求。首先,IIS 接收到请求,并将请求调度给 aspnet_isapi.dll;接下来,ASP.NET 引擎对已配置的 HTTP 模块进行初始化;最后将调用正确的 HTTP 处理程序,并呈现被请求的资源,将所生成的标记返回给 IIS 和请求客户端。


图一:IIS 和 ASP.NET 正在处理请求
鉴于上述逻辑,在线用户列表维护的核心功能将在一个自定义的Http模块中实现。具体来说,就是在其PostAuthenticateRequest事件中判断当前请求是否由自动刷新控件(上文已交代其存在原因)发出, 若是则不作任何处理;否则,将按当前用户标识(HttpContext.Current.Request.AnonymousID)判断当前在线用户实体是否已创建,并根据判断结果做如下处理(如图二所示):


图二 A、若尚未创建在线用户实体

若当前用户未登陆(判断HttpContext.Current.User.Identity.IsAuthenticated),则自动创建匿名用户实体并加入在线名单,否则继续下一步;

检测在线用户列表中是否有他人采用当前帐号登陆,无则按照当前标识&登陆用户标识创建普通用户(会员)并加入在线名单,若有则继续下一步;

判断是否禁止会员同时在多处登陆(EnableMemberLoginSingleton),若未禁止则直接创建普通用户并加入在线名单,若已设置禁止则继续下一步;

踢出使用当前帐号登陆的其他人,创建普通用户并加入在线名单。

B、若已创建在线用户实体

若当前在线用户实体为匿名用户(访客)且当前用户未登陆(判断HttpContext.Current.User.Identity.IsAuthenticated),或者当前在线用户实体为普通用户(会员)且当前用户已登陆,则直接更新当前在线用户的活动时间(ActiveTime)&自动刷新时间(RefreshTime),否则继续下一步;

转换当前在线用户实体(是匿名用户则更改为普通用户,是普通用户则更改为匿名用户)。

针对这个HttpModule还有以下三点补充:

登陆时,创建当前在线用户(会员)实体,并将其加入在线列表(若有必要,须先踢出使用用此帐号登陆的其他人)

会员注销时,应将当前用户从在线列表中移除。

创建一个利用脚本无刷新更新当前在线用户自动刷新时间(RefreshTime)的web控件,并将其放置在web系统的主要页面上。

在线用户的调用
在具体的web应用中可以自由调用当前在线用户实体,并且能够按条件(全部用户、全部访客、全部会员)获取全部的在线用户集合。

技术文档

下面列出了几个核心类的Class Diagram抓图。

oluUserInfo:在线用户信息

oluUserInfoProvider:在线用户信息提供者基类(使用本模块必须实现此类)

oluMonitor:在线用户监控器

oluHttpModule:在线用户模块的自定义Http模块

AutoRefreshControl:自动循环刷新控件



详细的描述就不写了,可以从 这里下载NDoc 生成的类库文档。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: