我们使用 NewRelic 来提供服务器端应用程序跟踪。
我们注意到我们的一些应用程序在 System.Web.Mvc.MvcHandler.BeginProcessRequest()
方法中持续花费大约 100 毫秒。
这发生在任何自定义 Controller 代码被调用之前(它是单独记录的,而不是累积记录的)——不清楚为什么它会在这个方法上花费这么多时间。
MVC在这个方法中会做什么样的事情?这可能只是请求排队吗?
[编辑:] 正如所怀疑的那样 - Scalayer 在下面的回答是正确的。我们删除并优化了所有 session 依赖项,并见证了应用程序可扩展性和稳定性的大幅提升
最佳答案
您可能看到的通常称为 .NET 中的线程敏捷性。
就主题标签下的结果(即 System.Web.HttpApplication.BeginRequest()
中的应用程序代码)而言,您可能看到的是线程敏捷性问题;在大多数情况下,您在这里看到的时间不一定是正在执行的代码,而是等待线程从读写器锁释放回它的 Web 上下文。
Application_BeginRequest()
“暂停”在 ASP.NET 网络堆栈中非常普遍。通常,当您在 BeginRequest 中看到较长的加载时间时,您正在处理 ASP.NET 线程敏捷性和/或线程锁 - 特别是在处理基于 IO 和 session 的操作时。这并不是一件坏事,这正是 .net 确保您的线程保持并发的方式。
时间间隔一般出现在BeginRequest和PreRequestHandlerExecute之间。如果应用程序正在向 session 写入多个内容,则 ASP.NET 将在 HttpContext.Current.Session
上发出读写器锁。
查看这是否是您可能面临的问题的一个好方法是检查线程 ID 以查看敏捷性是否是一个问题 - 对于给定的请求,ID 会有所不同。
例如。在调试时,也许您可以将以下内容添加到您的 Global.asax.cs
:
protected void Application_BeginRequest(Object sender, EventArgs e) {
Debug.WriteLine("BeginRequest_" + Thread.CurrentThread.ManagedThreadId.ToString());
}
打开调试输出窗口(从 Visual Studio:查看 >> 输出,然后从“显示输出自”下拉列表中选择“调试”)。
在调试时,点击一个你已经看过很长时间的页面。然后查看输出日志 - 如果您看到多个 ID,那么您可能遇到了这个问题。
这就是为什么您有时会看到延迟但其他时候却看不到的原因,应用程序代码使用 session 的方式可能略有不同,或者 session 或 IO 操作在页面之间可能更高或更低。
如果是这种情况,您可以采取一些措施来加快速度,具体取决于网站或每个给定页面上 session 的使用方式。
对于不修改session的页面:
<% @Page EnableSessionState="ReadOnly" %>
对于不使用 session 状态的页面:
<% @Page EnableSessionState="False" %>
如果应用不使用 session (web.config):
<configuration>
<system.web>
<sessionState mode="Off" />
</system.web>
</configuration>
让我们来看下面的例子:
用户加载一个页面,然后决定在第一个请求加载完成之前转到另一个页面 ASP.NET 将强制 session 锁定,导致新页面请求加载等待第一个页面请求完成。使用 ASP.NET MVC,每个操作都会锁定用户 session 以进行同步;导致同样的问题。
释放锁所花费的所有时间都将通过新遗留物报告,更不用说用户放弃 session 而返回的线程正在寻找不再存在的用户的那些时间。
顺便说一句,UpdatePanel 控件会导致相同的行为 -
http://msdn.microsoft.com/en-us/magazine/cc163413.aspx
可以做什么:
这个锁定问题是微软拥有 SessionStateUtility 类的原因之一 -
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstateutility.aspx
如果您遇到此问题,您可以覆盖默认行为 Redis 实现:https://github.com/angieslist/AL-Redis
基于 .net 的网站使用的默认状态提供程序有很多选项。但是通常知道这个事务时间表示线程正在被锁定并等待对服务器的请求完成。
关于c# - BeginProcessRequest() 中发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17064380/