使用Asp.net webforms我想像Google Analytics一样跟踪访问者信息。当然,我可以将Google Analytic用于此目的,但我想知道如何使用Asp.net 3.5和SQL Server 2008实现相同的目标。
我想存储访问者的IP,国家/地区,URL推荐人,每个页面请求的解析除了回发。我期待每天访问50k +。。
主要关注的是我希望以不应阻止当前请求的方式进行。
即一般情况下,当我们将数据保存到db时,当前请求在特定的SP调用语句上停止,并在完成执行SP或tsql语句时向前移动。我想遵循“插入和忘记”的方法。当我将参数传递给特定的事件或函数时,它应该在后台插入。
我在下面找到了替代方案:
1. PageAsynchTask
2. BeginExecuteNonQuery
3. Jquery Post方法和Web服务(但我对此没有信心,并且想知道我应该怎么做)
我希望我已经正确地提到了我的问题。
有人能告诉我哪一个更好吗?如果您有任何其他想法或更好的方法,请告诉我。非常感谢您的帮助。
答案 0 :(得分: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异步回发的解决方案。
这是否能为您提供问题的完整解决方案?
答案 1 :(得分:0)
第一种方法看起来不错。 (我推荐它。)但它有两个缺点:
第二种方法看起来不方便,可能会导致错误。 (当您的页面渲染速度超过查询处理速度时,您必须注意这种情况。我不确定当您的页面对象被销毁并且GC进入finalize()狂欢时查询未完成会发生什么。 ..但没什么好处,我假设。你可以通过在渲染后等待IAsyncResult.IsCompleted来避免它,但这很不方便。)
第三种方法是完全错误的。您应该在处理要记录的请求时启动服务器端的日志记录。但您仍然可以从服务器端调用Web服务。 (或获胜服务)。
就个人而言,我想在BeginRequest中实现日志记录以避免代码重复,但是你需要IsPostback ......仍然可能有一种解决方法。
答案 2 :(得分: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)
希望你明白这一点
所有最好的
答案 3 :(得分:0)
谈到服务器端,如果你在IIS上运行,并且你不需要绝对的实时信息,我建议你使用IIS日志。
没有什么比这更快,因为自IIS 1.0以来它已针对性能进行了优化
您可以在这些日志中添加自己的信息(HttpRequest.AppendToLog),它们具有标准格式,如果您想使用自定义内容,则有一个API(但如果您愿意,仍然可以使用文本解析器) ),有很多免费工具,例如Microsoft Log Parser,可以在SQL数据库(以及其他)中传输数据。