Discuz! 官方站

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 60096|回复: 55

【更新】在线时间更新机理分析(解决在线时间不更新和部分用户刷在线时间的问题)

[复制链接]
发表于 2011-6-23 15:24:54 | 显示全部楼层 |阅读模式
本帖最后由 nxy105 于 2011-8-31 10:22 编辑

最近在论坛上出现了许多站点的用户在线时间,或者在线用户的列表出现错误数据。针对以上现象,我简单介绍下论坛更新在线时间和在线用户的机理。(以下针对X2版本,其他各个版本的原理基本相同)。


所有的操作都在模板文件footer.htm中的一个不起眼的一条语句<!--{eval updatesession();}-->
<!--{eval updatesession();}-->调用的是function_core.php中的updatesession函数。

  1. function updatesession($force = false) {

  2.     global $_G;
  3.     static $updated = false;

  4.     if(!$updated) {
  5.         if($_G['uid']) {
  6.             if($_G['cookie']['ulastactivity']) {
  7.                 $ulastactivity = authcode($_G['cookie']['ulastactivity'], 'DECODE');
  8.             } else {
  9.                 $ulastactivity = getuserprofile('lastactivity');
  10.                 dsetcookie('ulastactivity', authcode($ulastactivity, 'ENCODE'), 31536000);
  11.             }
  12.         }
  13.         $discuz = & discuz_core::instance();
  14.         $oltimespan = $_G['setting']['oltimespan'];
  15.         $lastolupdate = $discuz->session->var['lastolupdate'];
复制代码
$oltimespan = $_G['setting']['oltimespan'];对应的值是后台全局--站点功能--其他--用户在线时间更新时长(分钟)的值。
  1.          if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $ulastactivity) > $oltimespan * 60) {
  2.             DB::query("UPDATE ".DB::table('common_onlinetime')."
  3.                 SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'
  4.                 WHERE uid='{$_G['uid']}'");
  5.             if(!DB::affected_rows()) {
  6.                 DB::insert('common_onlinetime', array(
  7.                     'uid' => $_G['uid'],
  8.                     'thismonth' => $oltimespan,
  9.                     'total' => $oltimespan,
  10.                     'lastupdate' => TIMESTAMP,
  11.                 ));
  12.             }
  13.             $discuz->session->set('lastolupdate', TIMESTAMP);
  14.         }
复制代码
如果是会员登录论坛,判断最近更新时间与当前时间的差大于用户在线时间更新时长时,会更新pre_common_onlinetime表(记录会员在线时间)里对应用户的对应字段的值,若没有对应用户,则添加一条记录。
  1.        foreach($discuz->session->var as $k => $v) {
  2.             if(isset($_G['member'][$k]) && $k != 'lastactivity') {
  3.                 $discuz->session->set($k, $_G['member'][$k]);
  4.             }
  5.         }

  6.         foreach($_G['action'] as $k => $v) {
  7.             $discuz->session->set($k, $v);
  8.         }

  9.         $discuz->session->update();

  10.         $updated = true;

复制代码
然后程序开始更新session(针对所有用户,包括未登录的游客),将session数据存到pre_common_session表里。
  1.        if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
  2.             if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
  3.                 $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  4.                 DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
  5.             }
  6.             dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
  7.             DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
  8.         }
  9.     }
  10.     return $updated;
  11. }
复制代码
最后根据用户最近的更新的时间,将计算出的用户在线时间,更新到pre_common_member_count表(统计用户记录信息表)里,我们看到的在线时间就是从此表里读取出来的,并且记录当前时间为用户最近活跃的时间。(注意:pre_common_member_count表中的在线时间是每12个小时更新一次)

以上有两个关键点:
在线时间的统计是由该函数执行和保存的,在线会员显示是直接读取的pre_common_session表中的数据

在线时间问题解决方案:
1.解决在线时间不更新的问题

第1步.检查模板
可能的原因是当前模板下footer.htm没有包含<!--{eval updatesession();}-->语句。
可以选择手动在footer.htm中添加,或者用原foot.htm覆盖当前footer.htm文件。
第2步.修改文件
如果站点某些活跃用户出现在在线时间不更新的情况。为了不影响设计逻辑,照以下修改updatesession()函数:
找到function_core.php的第66行附近
  1. if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
  2.             if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
  3.                      $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  4.                       DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
  5.              }
  6.             dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
  7.              DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
  8. }
复制代码
修改为
  1. if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
  2.           if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
  3.                    $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  4.                    DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);

  5.                    dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
  6.           }                        

  7.         DB::update('common_member_status', array('lastip' =>
  8. $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' =>
  9. TIMESTAMP), "uid='$_G[uid]'", 1);
  10. }
复制代码
2.解决用户刷在线时间
同样是修改function_core.php中的updatesession函数
找到
  1. $lastolupdate = $discuz->session->var['lastolupdate'];
复制代码
删除这句,将其替换成
  1. $lastolupdate = DB::result_first("SELECT lastupdate FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
复制代码
此方案解决用户刷在线时间,但已经刷过的用户,无法通过此方法恢复。


评分

3

查看全部评分

头像被屏蔽
发表于 2011-6-23 15:38:58 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

发表于 2011-6-23 17:27:12 | 显示全部楼层
测试了 还没解决

点评

如果有测试不能解决问题的情况,可以把站点信息pm给我,我帮你看看  发表于 2011-6-23 17:32
回复

使用道具 举报

发表于 2011-6-23 21:30:06 | 显示全部楼层
本帖最后由 尚哥哥 于 2011-6-23 21:40 编辑

板凳,谢谢了。
回复

使用道具 举报

发表于 2011-6-26 16:25:22 | 显示全部楼层
本帖最后由 shawn82 于 2011-6-26 16:31 编辑

我的footer里有<!--{eval updatesession();}-->这个正在用原本default的footer.htm

点评

footer.htm,码字疏忽~谢谢指出~  发表于 2011-6-26 16:27
回复

使用道具 举报

发表于 2011-6-26 16:37:48 | 显示全部楼层
我的footer内已经有了这个
<!--{eval updatesession();}-->

但是为什么问题依然存在

点评

如果不能解决可以把站点信息PM我,我帮你排查  发表于 2011-6-26 16:44
回复

使用道具 举报

头像被屏蔽
发表于 2011-6-28 17:37:15 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

发表于 2011-7-3 02:21:34 | 显示全部楼层
foot里有这段代码,还是会有部分会员的在线时间不更新,请问这个帖子还有效吗?我看到是针对1.5的


http://www.discuz.net/thread-1928444-1-1.html
回复

使用道具 举报

发表于 2011-7-5 11:54:57 | 显示全部楼层
本帖最后由 ●﹎мe|迷茫 于 2011-7-5 14:18 编辑

我站的在线时间不更新。。我去看了下数据库  发现这个表不更新。。pre_common_member_count   怎么才能让他更新  最好一次性解决   让他自动更新。。

www.99milian.com
回复

使用道具 举报

发表于 2011-7-8 09:20:25 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

腾讯云商标服务特惠!快速注册低至270元/件起,更有续展/宽展+延伸一站式服务、全场代金券补贴

小黑屋|Discuz! 官方站 ( 粤B2-20090059-165 )star

GMT+8, 2020-4-1 19:07

Powered by Discuz! X3.3

Copyright © 2001-2019 Tencent Cloud.

快速回复 返回顶部 返回列表