几年前给朋友珠宝公司开发过一套旺财珠宝库存管理系统,用得还是web Form老技术,但是更多的走Ashx+Ajax,但前端可是HTML5+jQuery+BootStrap等新技术,所以不论功能还是用户体验,都能很完美的满足用户要求(用户才不管你用的是什么技术,先进的和古老的都必须解决他的问题,然后还需要好用)。近期特别反馈说有些页面比较慢,我觉得用了几年了,数据库就近2个G了,可能是数据库查询的问题,也可能是程序执行的问题,也可能用户网络问题。数据库可以在服务器上用Sql Server Profiler进行查询分析,但页面上还得做点跟踪。于是就用Global.asax来实现,本来很方便的,但为了获取当前登录用户,需要在Global.asax中获取Session,花了点时间才搞定,记录下来分享一下。
本来想在Application_BeginRequest或者Session_Start里面获取的,可怎么也获取不到,于是翻看MSDN了解Global.asax的事件及执行顺序,在Application_AcquireRequestState中才获取到。
protected DateTime StartDateTime; protected void Application_BeginRequest(object sender, EventArgs e) { //开始执行时间 StartDateTime = DateTime.Now; } protected BaseUserInfo CurrentUserInfo; protected void Application_AcquireRequestState(object sender, EventArgs e) { if (Utilities.UserIsLogOn()) { CurrentUserInfo = Utilities.GetUserInfo(); } } protected void Application_EndRequest(object sender, EventArgs e) { DateTime endDateTime = DateTime.Now; TimeSpan ts = endDateTime - StartDateTime; //5秒以上的慢页面进行记录 if (ts.TotalMilliseconds >= 5000) { StringBuilder sb = new StringBuilder(); sb.Append("时间:" + endDateTime.ToString("yyyy-MM-dd hh:mm:ss fff") + ",当前请求URL:" + HttpContext.Current.Request.Url + ",请求的参数为:" + HttpContext.Current.Request.QueryString + ",页面加载的时间:" + ts.TotalMilliseconds + " 毫秒"); if (CurrentUserInfo != null) { sb.Append(",用户:" + CurrentUserInfo.UserName); } FileUtil.WriteMessage(sb.ToString(), BaseSystemInfo.StartupPath + "//Log//Slow/" + DateTime.Now.ToString(BaseSystemInfo.DateFormat) + ".txt"); } }
通过上述代码就可方便的获取哪些页面比较慢,何时、何人、何参数、何地(IP)发生的。
2018-05-11 03:33:18 947:[当前请求URL:Modules/WMS/ItemMaster/ItemMasterPlan.aspx;请求的参数为:;页面加载的时间:8151.3672 毫秒] 2018-05-11 04:09:25 181:[当前请求URL:Modules/WholesaleWMS/tools/WholesaleBPStatement.ashx?action=RefreshStatement;请求的参数为:action=RefreshStatement;页面加载的时间:19720.7031 毫秒] 2018-05-11 05:18:10 486:[当前请求URL:Modules/WMS/OutboundOrderLine/OutboundOrderLineListSummary.aspx;请求的参数为:;页面加载的时间:16742.1875 毫秒] 2018-05-12 10:33:59 305:[当前请求URL:Modules/WMS/PurchaseDemand/PurchaseDemandAdmin.aspx;请求的参数为:;页面加载的时间:9375.9765 毫秒] 2018-05-12 10:49:19 497:[当前请求URL:Modules/WMS/ItemMaster/ItemMasterPlan.aspx;请求的参数为:;页面加载的时间:5278.3203 毫秒] 2018-05-12 01:24:36 673:[当前请求URL:Modules/WMS/InboundOrderLine/InboundOrderLineListReport.aspx;请求的参数为:;页面加载的时间:11416.0156 毫秒] 2018-05-12 01:24:42 045:[当前请求URL:Modules/WMS/InboundOrderLine/InboundOrderLineListReport.aspx;请求的参数为:;页面加载的时间:6209.9609 毫秒] 2018-05-12 01:24:42 611:[当前请求URL:Modules/WMS/InboundOrderLine/InboundOrderLineListReport.aspx;请求的参数为:;页面加载的时间:10142.5781 毫秒] 2018-05-12 04:39:35 251:[当前请求URL:Modules/WMS/OutboundOrderLine/OutboundOrderLineListSummary.aspx;请求的参数为:;页面加载的时间:16623.0469 毫秒] 2018-05-12 04:51:31 401:[当前请求URL:Modules/WMS/OutboundOrderLine/OutboundOrderLineListSummary.aspx;请求的参数为:;页面加载的时间:16648.4375 毫秒] 2018-05-12 04:57:15 362:[当前请求URL:Modules/WMS/OutboundOrderLine/OutboundOrderLineListSummary.aspx;请求的参数为:;页面加载的时间:16552.7343 毫秒]
最后附上MSDN上对Global.asax的解释:
按执行顺序来解释一下Global.asax.cs中相应的事件处理方法的含义
- Application_BeginRequest:BeginRequest是在收到Request时第一个触发的事件,这个方法自然就是第一个执行的了。
- Application_AuthenticateRequest:当安全模块已经建立了当前用户的标识后执行。
- Application_AuthorizeRequest:当安全模块已经验证了当前用户的授权时执行。
- Application_ResolveRequestCache:当ASP.NET完成授权事件以使缓存模块从缓存中为请求提供服务时发生,从而跳过处理程序(页面或者是WebService)的执行。这样做可以改善网站的性能,这个事件还可以用来判断正文是不是从Cache中得到的。
- Application_AcquireRequestState:当ASP.NET获取当前请求所关联的当前状态(如Session)时执行(真是拗口啊,msdn上就这样写的,我自己想不出什么好句子了)。
- Application_PreRequestHandlerExecute:当ASP.Net即将把请求发送到处理程序对象(页面或者是WebService)之前执行。这个时候,Session就可以用了。
- Application_PostRequestHandlerExecute:当处理程序对象(页面或者是WebService)工作完成之后执行。
- Application_ReleaseRequestState:在ASP.NET执行完所有请求处理程序后执行。ReleaseRequestState事件将使当前状态数据被保存。
- Application_UpdateRequestCache:在ASP.NET执行完处理程序后,为了后续的请求而更新响应缓存时执行。
- Application_EndRequest:同上,EndRequest是在响应Request时最后一个触发的事件,这个方法自然就是最后一个执行的了。
再附上两个无顺序的,随时都可能执行的
- Application_PreSendRequestHeaders:向客户端发送Http标头之前执行。
- Application_PreSendRequestContent:向客户端发送Http正文之前执行。