确定“活动”状态 ASP.NET 站点的用户计数

发布于 2024-07-15 18:25:34 字数 382 浏览 4 评论 0原文

在 ASP.NET 站点上,有哪些技术可用于跟踪在任何给定时间点登录该站点的用户数量?

例如,我可以生成一个显示如下内容的报告:

        10:00am  11:00am  12:00pm  1:00pm  2:00pm ....
 3/25      25      32       45      40      37
 3/26      31      38       50      57      40
 3/27      28      37       46      35      20
 etc. 

编辑:不,我们没有使用 ASP.NET 会员提供程序,它使用基于本地/hacky 会话的方法来确定用户是否处于“已登录'状态。

On an ASP.NET site, what are some techniques that could be used to track how many users are logged in to the site at any given point in time?

So for example, I could produce a report showing something like this:

        10:00am  11:00am  12:00pm  1:00pm  2:00pm ....
 3/25      25      32       45      40      37
 3/26      31      38       50      57      40
 3/27      28      37       46      35      20
 etc. 

EDIT: No, we're not using ASP.NET Membership provider, it uses a home-grown/hacky session based method of determining whether or not a user is in 'logged in' status.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

心凉 2024-07-22 18:25:34

网站是否让用户登录? 如果是这样,那么您可以在用户每次请求新页面时更新用户表中的“上次访问”字段,然后每小时执行一次 SQL 查询,以获取最近一次访问中具有“上次访问”时间戳的每个人。 15 分钟左右(假设当前在网站上)。

如果您没有人登录,您可以通过 IP 地址而不是用户名轻松完成登录。 不过,使用这种方法,您可能会遇到一些代理问题(即来自同一公司网络的多个用户可能都来自同一个 IP 地址,因此他们在总数中仅算作一个用户),但这应该是最小的。

Does the website log the user in? If it does, then you can update a "Last Visit" field in the user table every time they request a new page, and then every hour, just do a SQL query that grabs everybody who has a "Last Visit" timestamp within the last 15 minutes or so (assumed to currently be on the site).

If you're not having people log in, you could just as easily do it by IP address instead of username. With this method, though, you may run into some proxy issues (ie multiple users from the same corporate network may all come from a single IP address, so they only count as one user in your totals), but that should be minimal.

痴骨ら 2024-07-22 18:25:34

这取决于您的网站。 如果您使用 ASP.Net 会员提供程序,则有一个方法:Membership.GetNumberOfUsersOnline() 可以告诉您有多少登录用户。 我相信还有性能计数器。 登录用户的概念是在过去 x 分钟内执行某项操作的用户,其中 x 是可配置的。

如果您想了解有多少活动,您还可以使用性能计数器来跟踪传入请求。

编辑

只是让您知道 SQL ASP 会员提供商通过在数据库中的字段上记录活动日期来实现此目的。 它只是查询 x 分钟内的所有活动。

我添加了一个客户端轮询功能,该功能每 2 分钟就会访问我们的服务器,因此当用户坐在页面上时,即使没有任何活动,我也知道他们在那里。 这也让我强制用户退出系统,提供了传递其他系统消息的方法。 有点不错。

This sort of depends on your site. If your using the ASP.Net Membership Providers there is a method: Membership.GetNumberOfUsersOnline() which can tell you how many logged in users there are. I believe there are also performance counters. The notion of a logged in user is a user who did something within the last x minutes where x is configurable.

You could also use performance counters to track incoming requests if you want to get a sense of how much activity there is.

Edit

Just so you know the SQL ASP Membership providers implements this by recording an activity date on a field in the DB. It when just queries it for all activity within x minutes.

I added a client side polling function which hits our server every 2 minutes, so while a user is sitting on the page I know they are there even if there is no activity. This also let me force the user out of the system, provides a method deliver other system messages. Kind of nice.

∞梦里开花 2024-07-22 18:25:34

如果使用 SQL Server 进行会话存储(即 模式在 web.config 中为“SQLServer”),则不能使用依赖于 Session_End 的解决方案global.asax,因为该方法永远不会被调用。

但是,假设 SQL Agent 正确运行 DeleteExpiredSessions 作业(安装 SQL State 时默认情况下应该如此),您只需针对会话运行以下 SQL D b:

SELECT COUNT(SessionId) FROM ASPStateTempSessions

If using SQL Server for Session storage (i.e. <sessionState> mode is "SQLServer" in web.config), you can't use a solution that relies on Session_End in global.asax, as the method will never be called.

However, assuming that SQL Agent is running the DeleteExpiredSessions job correctly (which it should be by default when SQL State was installed), you can just run the following SQL against the Session Db:

SELECT COUNT(SessionId) FROM ASPStateTempSessions
_畞蕅 2024-07-22 18:25:34

在 Global.asax 上

protected void Application_Start(object sender, EventArgs e)
        {
            Application["SessionCount"] = 0;
        }

        protected void Session_Start(object sender, EventArgs e)
        {
            Application.Lock();
            Application["SessionCount"] = Convert.ToInt32(Application["SessionCount"]) + 1;
            Application.UnLock();
        }

        protected void Session_End(object sender, EventArgs e)
        {
            Application.Lock();
            Application["SessionCount"] = Convert.ToInt32(Application["SessionCount"]) - 1;
            Application.UnLock();
        }

获取您想要的页面上的 Application["SessionCount"]

On Global.asax

protected void Application_Start(object sender, EventArgs e)
        {
            Application["SessionCount"] = 0;
        }

        protected void Session_Start(object sender, EventArgs e)
        {
            Application.Lock();
            Application["SessionCount"] = Convert.ToInt32(Application["SessionCount"]) + 1;
            Application.UnLock();
        }

        protected void Session_End(object sender, EventArgs e)
        {
            Application.Lock();
            Application["SessionCount"] = Convert.ToInt32(Application["SessionCount"]) - 1;
            Application.UnLock();
        }

Get Application["SessionCount"] on the page you want

两相知 2024-07-22 18:25:34

我认为我过去使用的是 Global.asax 函数,主要以 Session_Start 和 Session_End 为中心,随着 Start 增加计数,然后由于会话超时,结束有点棘手。 如果您不太关心计数的准确度,那么您可以到此为止。

如果没有,那么您可能会结合使用 javascript onUnload 事件和某种 ajax 请求来使会话无效并减去用户。 该事件必须查看用户是否确实离开该页面或只是前往网站上的另一个页面。

无论如何,从这里开始。 我记得与 ASP 站点有关,所以肯定有一些关于此方法的信息。

I think what I've used in the past was the Global.asax functions mainly centering around the Session_Start and Session_End, increasing a count with the Start, and then the end is a bit tricky because of the session timeout. If you are not concerned a lot with how exactly accurate the count is then you can stop here.

If not then you'd probably use a combination of the javascript onUnload event with some sort of ajax request to invalidate the session and subtract the user. The event would have to see if the user was actually leaving the page or just going to another page on the site.

Anyway, start there. I remember having to do with ASP sites so there is definately some information out there on this method.

呢古 2024-07-22 18:25:34

ASP.NET 性能对象中有活动会话的性能监视器统计信息,您可以跟踪所有实例或单个应用程序。 您可以通过管理工具性能访问这些统计信息,或通过WMI以编程方式访问这些统计信息。

一个非常基本的 PowerShell 脚本来获取此类计数器的总数:

(Get-WmiObject Win32_PerfRawData_ASPNET_ASPNETApplications SessionsActive).SessionsActive

过滤器应该能够获取特定站点的统计信息。

There are performance monitor stats for Sessions Active within the ASP.NET performance objects, and you can track all instances, or individual apps. You can access these stats through Admin ToolsPerformance, or programmatically via WMI.

A very basic PowerShell script to get such a total of such counters:

(Get-WmiObject Win32_PerfRawData_ASPNET_ASPNETApplications SessionsActive).SessionsActive

A filter should be able to get the stat for a specific site.

淡淡の花香 2024-07-22 18:25:34

首先将会话超时设置为 1 分钟。

创建一个简单的 heartbeat.aspx 页面,不包含 HTML 内容,只需使用以下 javascript 代码:

<html>
  <head>
  <script language="javascript">
  function reloadPage()
  {
    window.navigate("heartbeat.aspx");
  }
  </script>
  </head>
<body onload="window. setTimeout(‘reloadPage()’, 30000)">
</body>
</html>

这将每 30 秒重新请求一次并保持会话处于活动状态。

将 heatbeat.aspx 页面放入隐藏框架中。

要获取用户计数,只需在 Global.asax 中的 Session_Start 和 Session_End 事件中使用静态计数器即可获取会话计数。

First set Session timeout for 1 minute.

Create a simple heartbeat.aspx page with no HTML content just the following javascript code:

<html>
  <head>
  <script language="javascript">
  function reloadPage()
  {
    window.navigate("heartbeat.aspx");
  }
  </script>
  </head>
<body onload="window. setTimeout(‘reloadPage()’, 30000)">
</body>
</html>

This will re-request itself every 30 seconds and keep session alive.

Put heatbeat.aspx page in a hidden frame.

To get user count just get session count by using static counter in Session_Start and Session_End events in Global.asax.

微凉 2024-07-22 18:25:34

如果您使用 InProc 会话状态,则可以在 global.asax 中这样做

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    Application("ActiveSessionCount") = 0
End Sub

Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
    Application("ActiveSessionCount") += 1
End Sub

Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
    Application("ActiveSessionCount") -= 1
End Sub

要访问 Web 表单上的值也同样简单

Dim Count as Integer = Application("ActiveSessionCount")

If you are using InProc session state, you can do it like this in global.asax

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    Application("ActiveSessionCount") = 0
End Sub

Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
    Application("ActiveSessionCount") += 1
End Sub

Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
    Application("ActiveSessionCount") -= 1
End Sub

To access the value on a web form is just as simple

Dim Count as Integer = Application("ActiveSessionCount")
独留℉清风醉 2024-07-22 18:25:34
public class ActiveUsers
{
    private static List<LastUserActivity> users;
    private static object syncroot = new object();
    private static DateTime lastPruned;

    public static int SessionLength = 20;

    static ActiveUsers()
    {
        users = new List<LastUserActivity>();
        lastPruned = DateTime.UtcNow;
    }

    public void RecordUserActivity(int userId)
    {
        lock (syncroot)
        {
            var user = users.FirstOrDefault(x => x.UserId == userId);
            if (user == null)
            {
                user = new LastUserActivity() { UserId = userId };
                users.Add(user);
            }
            user.UtcTime = DateTime.UtcNow;

            if (lastPruned.AddMinutes(5) < DateTime.UtcNow)
            {
                Prune();
                lastPruned = DateTime.UtcNow;
            }
        }
    }

    private static void Prune()
    {
        users.RemoveAll(x => x.UtcTime.AddMinutes(SessionLength) < DateTime.UtcNow);
    }

    public int GetActiveUsers()
    {
        return users.Count;
    }
}
public class LastUserActivity
{
    public int UserId { get; set; }
    public DateTime UtcTime { get; set; }
}

将对 ActiveUsers 的调用添加到 global.asax 中的方法中(例如 BeginRequest、AcquireRequestState)。

public class ActiveUsers
{
    private static List<LastUserActivity> users;
    private static object syncroot = new object();
    private static DateTime lastPruned;

    public static int SessionLength = 20;

    static ActiveUsers()
    {
        users = new List<LastUserActivity>();
        lastPruned = DateTime.UtcNow;
    }

    public void RecordUserActivity(int userId)
    {
        lock (syncroot)
        {
            var user = users.FirstOrDefault(x => x.UserId == userId);
            if (user == null)
            {
                user = new LastUserActivity() { UserId = userId };
                users.Add(user);
            }
            user.UtcTime = DateTime.UtcNow;

            if (lastPruned.AddMinutes(5) < DateTime.UtcNow)
            {
                Prune();
                lastPruned = DateTime.UtcNow;
            }
        }
    }

    private static void Prune()
    {
        users.RemoveAll(x => x.UtcTime.AddMinutes(SessionLength) < DateTime.UtcNow);
    }

    public int GetActiveUsers()
    {
        return users.Count;
    }
}
public class LastUserActivity
{
    public int UserId { get; set; }
    public DateTime UtcTime { get; set; }
}

Add a call to ActiveUsers into a method in global.asax (eg. BeginRequest, AcquireRequestState).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文