10

我们的客户想知道在线并且当前正在使用我们为他们编写的自定义应用程序。我和他们讨论过,这不需要很准确,更多的猜测会起作用。

所以我的想法是确定用户活动的 15 分钟时间间隔。我这样做的一些想法如下:

  1. 每次他们执行访问数据库或请求网页的操作时,用他们上次活动的日期和时间标记他们的用户记录......虽然这可能是数据库密集型的。

  2. 从我们的软件发送“谁在线请求”,寻找响应,这可以在预定的时间间隔内完成,然后在用户记录上标记我收到的每个响应的当前日期和时间。

你怎么认为?您将如何处理这种情况?

澄清

如果可能的话,我想为 Windows 或 Web 使用相同的架构。我有一个与多个用户界面交互的业务逻辑层,可以是 Windows 或 Web。

通过Windows,我的意思是客户端-服务器。

澄清

我使用的是 n 层架构,因此我的业务对象处理与表示层的所有交互。该表示层可以提供客户端-服务器 Windows 应用程序、Web 应用程序、Web 服务等。

它不是一个高流量的应用程序,因为它是为我们的一个客户开发的,最多可能有 100 个用户。

4

12 回答 12

5

我们的解决方案是除了我们的“会话”表(跟踪谁在这里)之外,还维护一个“事务”表(跟踪所做的事情)。UPDATE、INSERT 和 DELETE 指令都通过“事务”对象进行管理,一旦在数据库上成功执行,这些 SQL 指令中的每一个都将存储在“事务”表中(取决于更新的表:我们有可能专门遵循一些表格并忽略其他表格)。这个“Transaction”表还有transactiontType(I代表INSERT,D代表DELETE,U代表UPDATE)、transactionDateTime等字段,还有一个外键“sessionId”,最后告诉我们是谁发出了指令。甚至可以通过一些代码来确定谁在何时做了什么(Gus 在周一创建了记录,

此解决方案的优点是:

  1. 您可以说出“谁和什么时候”,并将其展示给您的用户!(您需要一些代码来分析 SQL 语句)
  2. 如果你的数据被复制了,并且复制失败了,你可以通过这个表重建你的数据库

缺点是

  1. 每月 100 000 次数据更新意味着 Tbl_Transaction 中有 100 000 条记录
  2. 最后,该表往往占数据库容量的 99%

我们的选择:每天早上自动删除所有超过90天的记录

于 2008-10-06T18:11:51.010 回答
2

我以前见过策略 1 的工作。当然,网站很小。

于 2008-10-06T13:22:23.497 回答
1

我想知道像 stackoverflow 这样的网站是如何做到的?

他们必须针对一个特定的事件,因为我只是在网站上使用工具,看看我的个人资料,仍然会说8 分钟前最后一次看到的内容。

于 2008-10-06T15:43:20.433 回答
0

我只是在数据库中删除一个日志记录表。

UserId int FK
Action char(3) ('in' or 'out')
Time DateTime

当有人登录或注销时,您可以在表中删除一条新记录,或者更新用户的最后一条记录。

于 2008-10-06T13:23:42.447 回答
0

我已经使用过许多使用您列出的第一种方法的系统,经过一些仔细的计划,它可以以一种实际上没有太大影响的方式完成。

这完全取决于您尝试跟踪的时间/方式/内容。如果您需要跟踪多个会话,我通常会看到使用绑定到用户帐户的会话系统的人,然后在特定的经过时间之前该会话被认为是无效的。

如果您确实正在寻找当前在线,那么您的第一个选择是最好的。

于 2008-10-06T13:24:11.400 回答
0

如果您有会话数据,请使用它。大多数会话系统已经有时间戳,因此它们可以使未使用 x 分钟的会话过期。

于 2008-10-06T13:24:52.197 回答
0

您可以在每次创建用户会话时增加一个全局变量,并在它被销毁时减少它。这样,您将始终知道在任何特定时刻有多少用户在线。

另一方面,如果您想随着时间的推移对其进行监控,我认为将会话开始和结束记录到数据库是最好的选择,并且您可以在事后通过简单的查询来计算用户活动。

于 2008-10-06T13:30:10.280 回答
0

[免责声明 1 --- Java 解决方案]

如果给每个有意义的用户一个 Session,那么您可以编写自己的 SessionListener 实现来跟踪每个已创建和销毁的会话。

[免责声明 2 --- 代码未经测试或编译]

public class ActiveSessionsListener implements HttpSessionListener {
    public void sessionCreated(HttpSessionEvent e) {
        ServletContext ctx = e.getSession().getServletContext();
        synchronized (ctx) {
            Integer count = ctx.getAttribute("SESSION_COUNT");
            if (count == null) { count = new Integer(0); }
            ctx.setAttribute("SESSION_COUNT", new Integer(count.intValue() + 1);
        }
    }
    public void sessionDestroyed(HttpSessionEvent e) {
        ... similar for decrement ...    
    }
}

并在您的 web.xml 中注册:

<listener-class>com.acme.ActiveSessionsListener</listener-class>

希望这可以帮助。

于 2008-10-06T13:35:10.973 回答
0

Web 应用程序解决方案的唯一问题是您通常不知道何时有人退出。显然,如果您有登录/身份验证要求,您可以捕获某人何时登录,并且作为您的数据访问代码的一部分,您可以在某人访问数据库时进行登录。但是您将不得不接受当一个人注销时会有可靠的捕获方式 - 许多人会离开该站点而不采取“注销”操作。

于 2008-10-06T13:45:30.797 回答
0

我想使用触发器将是一个合理的选择,它可以使您不必处理 Web 和非 Web 环境(或任何其他环境)之间的任何逻辑差异。但是,这仅捕获对环境的更改,并且在执行 select 语句时不做任何事情。但是,如果您的应用程序中的所有命令都通过存储过程运行,则可以克服这一点。

于 2008-10-06T13:48:26.033 回答
0

对于网络应用程序,“在线”的概念有点模糊。您真正能做的最好的事情是“在最后 X 分钟内提出请求”或者“在最后 X 分钟内通过身份验证”。

选择一组事件(发出请求、执行更新、已验证...),并将它们记录到数据库表中。

将它们记录到单独数据库中的表中

于 2008-10-07T14:30:46.930 回答
0

我刚刚为我的网站实施了最后一次看到的系统。您的第一个选项类似,但我仅每 +-5 分钟更新一次。它适用于我的情况,但大型网站可能需要一些额外的东西。

<?php
function updateLastSeen($user_ref, $session_id, $db) { /*Parameters: The user's primary key, the user's session id, the connection to the database*/
  $timestamp = date('Y-m-d H:i:s');
  if ($session_id !== '') {
    /*logged in*/
    $sql_check = "SELECT user_id FROM user_last_seen WHERE user_id = ?";
    $stmt_check = $db->prepare($sql_check);
    $stmt_check->bind_param('s', $user_ref);
    $result_check = $stmt_check->execute();
    $stmt_result_check = $stmt_check->get_result();
    if ($stmt_result_check->num_rows > 0) { /*If the user's last seen was previously recorded, update his record*/
      $sql = "UPDATE user_last_seen SET last_seen = ? WHERE user_id = ?"; 
    } else { /*Otherwise, insert a record for him*/
      $sql = "INSERT INTO user_last_seen (last_seen, user_id) VALUES (?,?)";
    }
    $stmt = $db->prepare($sql);
    $stmt->bind_param('ss', $timestamp, $user_ref);
    $result = $stmt->execute();
  }
}
if( !isset($_SESSION['lastSeen']) ){ /*User logs into the website or lands on the current page, create a lastSeen variable*/
  $_SESSION['lastSeen'] = time();
  updateLastSeen($user_ref, $session_id, $db);
} else {
  $last_seen_time_difference = (time() - $_SESSION['lastSeen']) / 60;
  if ($last_seen_time_difference > 5) { //if the difference between now and the lastSeen is 5 minutes or more, record his last seen.
    updateLastSeen($user_ref, $session_id, $db);   
    $_SESSION['lastSeen'] = time(); /*after updating the database, reset the lastSeen time to now.*/
  }/* else {
    //do nothing. Don't update database if lastSeen is less than 5 minutes ago. This prevents unnecessary database hits.
  }*/
}
于 2019-03-24T13:29:53.697 回答