Discuz!NT在线用户自动归零Bug分析及解决办法

使用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试过,使用前注意备份