1

使用 Asp.net 网络表单,我想像 Google Analytics 一样跟踪访问者信息。当然,我可以为此目的使用 Google Analytic,但我想知道如何使用 Asp.net 3.5 和 SQL Server 2008 实现相同的目标。

我想在除回发之外的每个页面请求上存储 IP、国家、访问者的 URL 引用者、分辨率。我预计每天有 50k+ 次访问。.

主要关心的是我想以一种不应该阻止当前请求的方式来做。

即通常当我们将数据保存到数据库时会发生这种情况,当前请求在特定的 SP 调用语句上停止,并在它完成执行 SP 或 tsql 语句时向前移动。我想遵循“插入并忘记”的方法。当我将参数传递给特定事件或函数时,它应该在后台插入。

我找到了以下替代方案:
1. PageAsynchTask
2. BeginExecuteNonQuery
3. Jquery Post 方法和 Webservice (但我对此没有信心,想知道我应该如何去做)

我希望我已经正确地提到了我的问题。

谁能告诉我哪种方法更好?如果您有任何其他想法或比列出的更好的方法,也请告诉我。您的帮助将不胜感激。

4

4 回答 4

1

服务器端任何后台线程的问题是每个请求都将占用两个线程。一种用于服务 ASP.NET 请求,另一种用于记录您要记录的内容。因此,由于 ASP.NET 线程耗尽,您最终会遇到可伸缩性问题。在数据库中记录每个请求是一个很大的禁忌。

最好的办法是使用一些高性能的日志库来写入日志文件。日志库针对多线程日志进行了高度优化。他们不会在每次调用时产生 I/O 调用。日志存储在内存缓冲区中并定期刷新。您应该使用 EntLib 或 Log4net 进行日志记录。

您可以使用拦截每个 GET、POST 的 HttpModule,然后在 HttpModule 中检查 Request.Url 是否为 aspx。然后您可以阅读 Request.Headers["__ASYNCPOST"] 并查看它是否为“true”,这意味着它是 UpdatePanel 异步更新。如果所有这些条件都为真,您只需将请求记录到一个日志文件中,该文件存储

您可以从以下位置获取客户端 IP:

HttpContext.Current.Request.UserHostAddress; 
or 
HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

要获取机器的 IP 地址而不是代理,请使用以下代码

HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

但是你不能得到这个国家。您必须在日志文件中记录 IP,然后使用一些控制台应用程序或作业来处理日志文件,这将解析 IP 所在的国家/地区。您需要获取一些 IP->Country 数据库来完成这项工作。我以前使用过http://www.maxmind.com/app/geoip_country

对于屏幕大小,您将不得不依赖一些 javascript。在每个页面上使用 javascript,在客户端找到屏幕大小并存储在 cookie 中。

var screenW = 640, screenH = 480;
if (parseInt(navigator.appVersion)>3) {
 screenW = screen.width;
 screenH = screen.height;
}
else if (navigator.appName == "Netscape" 
    && parseInt(navigator.appVersion)==3
    && navigator.javaEnabled()
   ) 
{
 var jToolkit = java.awt.Toolkit.getDefaultToolkit();
 var jScreenSize = jToolkit.getScreenSize();
 screenW = jScreenSize.width;
 screenH = jScreenSize.height;
}

将其存储在 cookie 中(我没有显示该代码)后,您可以使用 Request.Cookies 从 HttpModule 读取屏幕尺寸,然后将其记录到日志文件中。

因此,这为您提供了记录 IP、屏幕大小、从 IP 查找国家/地区以及从日志中过滤 UpdatePanel 异步回发的解决方案。

这是否为您提供了问题的完整解决方案?

于 2011-05-07T13:39:37.403 回答
0

第一种方法看起来不错。(我推荐它。)但它有两个缺点:

  1. 请求仍然会阻塞,直到任务完成(或超时中止)。
  2. 您必须在每个页面上注册您的任务。

第二种方法看起来不方便,可能会导致错误。(您必须注意页面呈现速度快于查询处理速度的情况。我不确定当您的页面对象被销毁并且 GC 继续 finalize() 狂欢时,如果您的查询未完成会发生什么......但我认为没什么好处。您可以通过在渲染后等待 IAsyncResult.IsCompleted 来避免它,但这很不方便。)

第三种方法是完全错误的。在处理要记录的请求时,您应该在服务器端启动日志记录。但是您仍然可以从服务器端调用 Web 服务。(或赢得服务)。

就个人而言,我想在 BeginRequest 中实现日志记录以避免代码重复,但您需要 IsPostback... 仍然可能有一种解决方法。

于 2011-04-26T05:12:24.743 回答
0

您好,您可以触发异步请求而无需等待响应。这里我有一些实现的代码..

为此,您需要创建一个 Web 服务来执行数据库操作,或者您可以将其用于整个事件处理。

从服务器端,您必须像这样异步调用 Web 服务

声明私人代表

private delegate void ReEntryDelegate(long CaseID, string MessageText);

现在该方法将包含这样的 Web 服务调用

WebServiceTest.Notification service = new WebServiceTest.Notification();
IAsyncResult handle;
ReEntryDelegate objAscReEntry = new ReEntryDelegate(service.ReEntryNotifications);
handle = objAscReEntry.BeginInvoke(CaseID, MessageText, null, null);
break;

并且变量值将通过这里的方法传递(CaseID,MessageText)

希望这对你来说很清楚

祝一切顺利

于 2011-05-04T07:17:27.840 回答
0

说到服务器端,如果你在 IIS 上运行,并且你不需要绝对的实时信息,我建议你使用 IIS 日志。

没有比这更快的了,因为它从 IIS 1.0 开始就针对性能进行了优化

您可以在这些日志 ( HttpRequest.AppendToLog )中附加您自己的信息,它们具有标准格式,如果您想用它做自定义的事情,有一个 API(但如果您愿意,您仍然可以使用文本解析器),并且有许多免费工具,例如Microsoft Log Parser,它可以在 SQL 数据库中传输数据(等等)。

于 2011-05-04T07:27:59.887 回答