跟踪每个请求的访客信息

发布于 2024-11-03 11:59:58 字数 826 浏览 2 评论 0原文

我想使用 Asp.net webforms 跟踪访问者信息,就像 Google Analytics 一样。当然,我可以使用 Google Analytic 来实现此目的,但我想知道如何使用 Asp.net 3.5 和 SQL Server 2008 实现同样的效果。

我想存储访问者的 IP、国家/地区、URL Referrer,除回发之外的每个页面请求的分辨率。我预计每天的访问量将超过 5 万次。

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

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

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

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

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

Using Asp.net webforms I want to track down visitor info just like Google Analytics does. Of course, I can use Google Analytic for this purpose but I want to know how can I achieve the same thing with Asp.net 3.5 and SQL Server 2008.

I want to store IP, Country, URL Referrer of the visitor, Resolution on each page request except postback. I am expecting 50k+ visit everyday..

Main concern is I want to do it in a way that it should not block current request.

i.e In general it happens when we save data in to db, current request stops on particular SP calling statment and moves ahead when it finishes executing SP or tsql statement. I want to follow "Insert and Forget" approach. It should insert in background when I pass parameter to particular event or function.

I found below alternatives for this :
1. PageAsynchTask
2. BeginExecuteNonQuery
3. Jquery Post method and Webservice (But I am not confident about this, and wondering how should I go about it)

I hope I've mentioned my problem properly.

Can anybody tell me which one is better approach? Also let me know if you've any other ideas or better approach than the listed one. Your help will be really appreciated.

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

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

发布评论

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

评论(4

小草泠泠 2024-11-10 11:59:59

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

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

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

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

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

The first approach is looking good. (And I recommend it.) But it has 2 downsides:

  1. Request will still block until task completes (or aborts on timeout).
  2. You'll have to register your Task on every page.

The second approach looks inconvenient and might lead to errors. (You have to watch for a situation when your page renders faster than your query is processed. I'm not sure what will happen if your query is not complete when your page object is destroyed and GC goes on finalize() spree... but nothing good, I assume. You can avoid it by waiting for IAsyncResult.IsCompleted after render, but that's inconvenient.)

The third method is plain wrong. You should initiate your logging on the server side while processing the request you're going to log. But you still can call a web service from the server side. (Or a win service).

Personally, I'd like to implement logging in BeginRequest to avoid code duplication, but you need IsPostback... Still there might be a workaround.

音盲 2024-11-10 11:59:59

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

为此,您需要创建一个 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)

希望这对您

来说 是清楚的最好的

Hii,
you can fire an asynchronous request and don't wait for response.
here i have some implemented code..

for that you need to create a web service to do your database operation or you can use it for your whole event handling.

from server side you have to call the web service asynchronously like this

Declare a Private Delegate

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

Now the method will contain web service calling like this

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

And the variable values will be passed by method here (CaseID,MessageText)

Hope this is clear to you

All the Best

被你宠の有点坏 2024-11-10 11:59:58

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

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

您可以使用 HttpModule 来拦截每个 GET、POST,然后在 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-> 国家/地区数据库才能完成这项工作。我之前使用过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 异步回发的解决方案。

这能为您提供问题的完整解决方案吗?

Problems with any background thread in server side is each and every request is going to occupy two threads. One for serving the ASP.NET request and one for logging the stuff you want to log. So, you end up having scalability issues due to exhaustion of ASP.NET threads. And logging each and every request in database is a big no no.

Best is to just write to log files using some high performance logging library. Logging libraries are highly optimized for multi-threaded logging. They don't produce I/O calls on each and every call. Logs are stored in a memory buffer and flushed periodically. You should use EntLib or Log4net for logging.

You can use an HttpModule that intercepts each and every GET, POST and then inside the HttpModule you can check whether the Request.Url is an aspx or not. Then you can read Request.Headers["__ASYNCPOST"] and see if it's "true", which means it's an UpdatePanel async update. If all these conditions are true, you just log the request into a log file that stores the

You can get the client IP from:

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

To get the IP address of the machine and not the proxy use the following code

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

However you cannot get the country. You will have to log the IP in your log files and then process the log files using some console application or job which will resolve the country of the IP. You need to get some IP->Country database to do the job. I have used http://www.maxmind.com/app/geoip_country before.

For screen size, you will have to rely on some javascript. Use a javascript on each page that finds the size of the screen on the client side and stores in a 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;
}

Once you store it in a cookie (I haven't shown that code), you can read the screen dimensions from the HttpModule by using Request.Cookies and then log it in the log file.

So, this gives you solution for logging IP, screensize, finding country from IP, and filtering UpdatePanel async postback from logging.

Does this give you a complete solution to the problem?

古镇旧梦 2024-11-10 11:59:58

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

没有比这更快的了,因为自 IIS 1.0 以来它已经针对性能进行了优化。

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

Talking about server side, if you're running on IIS, and you don't need absolute real time information, I recommend you use IIS logs.

There is nothing faster than this, as it's been optimized for performance since IIS 1.0

You can append your own information in these logs (HttpRequest.AppendToLog), they have a standard format, there is an API if you want to do custom things with it (but you can still use text parser if you prefer), and there are a lots of free tools, for example Microsoft Log Parser which can transfer data in a SQL database (among others).

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