使用Discuz!NT一段时间的,最近发现论坛上面的在线用户频繁归零,以前都没有出现过这样的错误,对服务器进行检查后,确定不是服务器的问题,于是就考虑是不是Discuz!NT的Bug
幸好Discuz!NT是开源的,于是从官网Down源代码下来解读当中的奥秘
在源代码中找到了下面一段:
/// <summary>
/// 复位在线表, 如果系统未重启, 仅是应用程序重新启动, 则不会重新创建
/// </summary>
/// <returns></returns>
public static int ResetOnlineList()
{
try
{
// 取得在线表最后一条记录的tickcount字段 (因为本功能不要求特别精确)
//int tickcount = DatabaseProvider.GetInstance().GetLastTickCount();
// 如果距离现在系统运行时间小于10分钟
if (System.Environment.TickCount < 600000)
{
return InitOnlineList();
}
return -1;
}
catch
{
try
{
return InitOnlineList();
}
catch
{
return -1;
}
}
}
从上面的代码可以看出如果系统运行时间大于10分钟,就算应用程序重新启动, 也不会归零在线用户表的,但Discuz!NT似乎忽略了一点,就是System.Environment.TickCount的值
引用Msdn中的一段话
该属性的值从系统计时器派生,并以 32 位有符号整数的形式存储。因此,如果系统连续运行,TickCount 将在约 24.9 天内从零递增至 Int32.MaxValue,然后跳至 Int32.MinValue(这是一个负数),再在接下来的 24.9 天内递增至零。
也就是说当过了24.9天之后,System.Environment.TickCount的值就为负数,System.Environment.TickCount < 600000的值就为True,在线用户表就会经常被重建归零
知道原理后有什么解决办法呢?
1、最笨的办法重启服务器,这样的话System.Environment.TickCount的值就会归零,你又能用24.9天了
2、如果懂得编程的话就Down源代码下来,把判断逻辑修改为:
if (System.Environment.TickCount < 600000 && System.Environment.TickCount >= 0)
再重新编译DLL,覆盖上去
我这有个已经编译好的文件: Discuz.Forum.rar (86.04 kb)
注:该文件使用2.0的源代码编译的,2.1由于没有公开源代码,所以未能编译,补丁没在2.1试过,使用前注意备份