NewRelic、异步HTTP处理程序和AcquireRequestState

24

我在一个分布式的ASP.NET Web应用程序中遇到了一个异步处理程序的问题。首先让我解释一个使用案例:

  • 该应用程序在安装有.NET Framework 4.5.2的Win 2012机器上使用IIS 8
  • 应用程序通过web.config禁用了Session和身份验证模块,就像这样:

         <system.webServer>
           ....
           <modules>
                <remove name="WindowsAuthentication" />
                <remove name="Session" />
                <remove name="FormsAuthentication" />
            </modules>
         </system.webServer>
    
  • 应用程序使用自定义异步Web处理程序来为特定请求提供服务

  • 应用程序的流量非常大(每个服务器每分钟约50,000个请求,异步处理程序每个服务器每分钟约10,000个请求,所有这些请求都由NewRelic跟踪)
  • 应用程序通过多个w3wp进程(2个w3wp进程)和多个虚拟服务器(约10个服务器)进行分发
  • 应用程序具有大量连接

所有正常的(同步请求)都工作正常,但做更多工作的异步请求(这就是我们使用异步请求的原因)经常很慢,但NewRelic报告它很慢是因为“AcquireRequestState”。现在我在Google和Stack Overflow上查看过,这个事件与创建会话有关,但我们已经在web.config中禁用了会话。有人知道“AcquireRequestState”还能干什么吗?我们漏掉了一些删除会话状态的地方吗?将其从web.config添加到machine.config并没有起任何作用...

这是NewRelic中请求的代码片段:

   **Slowest components   Count Duration     %   **
     AcquireRequestState    1   12,600 ms   100%  --> WTF?
     ExecuteRequestHandler  1   5.01 ms     0%
     Integrated Pipeline    1   0.334 ms    0%
     UpdateRequestCache     1   0.3 ms      0%
     EndRequest             1   0.168 ms    0%
     AuthenticateRequest    1   0.161 ms    0%
     Total time                 12,600 ms   100%

编辑: 我在 web.config 文件的 <system.web> 部分中有 <sessionState mode="Off" />,所以不是这个问题。

翻译为:

编辑:我在web.config文件的<system.web>部分中有<sessionState mode="Off" />,所以它不是问题的原因。


据我所知,您没有加载模块,但会话仍处于“启用”状态(默认情况下)- 关于<sessionState mode="Off">system.web中。希望对您有所帮助... - EdSF
我在web.config中有<sessionState mode="Off" />,所以不是那个问题。我会编辑它以添加这些信息。 - lord.fist
这是特定于浏览器(仅限IE)还是适用于所有浏览器?...找到了这篇文章:https://forums.iis.net/t/1169137.aspx - Asons
@lord.fist 你找到问题的原因了吗?我们遇到了完全相同的问题。 - Tomas
1
@lord.fist最近有没有进一步的发展?因为我们每天都会收到大约10个这样的警报,就像在New Relic中所显示的那样。我们承受着类似的负载,但是无法弄清楚可能导致这些少数异常值的原因。 - DavidG
显示剩余7条评论
3个回答

1

我研究了这个问题,因为我们遇到了类似的问题,我找到了这个论坛帖子,其中有一个有趣的回复是:

不幸的是,问题并不像简单地关闭sessionState那样简单。实际上,在描述AcquireRequestState的挑战时,其中一个关键短语是“例如,当此事件被触发时,会话状态”。在深入研究这个问题(实际上是查看.NET源代码)时,我们可以看到当执行EventHandler或创建RequestNotification对象时会调用它。我敢说还有其他方法和/或事件,当调用时,将引发AcquireRequestState事件。追踪所有这些表示一定程度的困难。似乎在更规范的会话状态讨论之外,很少有人谈论这个问题。 我们最常见到此事件被触发的地方肯定与会话状态管理有关。但是,这些事件明显仍然可能被触发的异常情况也存在。甚至可以直接从应用程序代码中调用它。代理所面临的问题是可以确定事件,但很少能确定来源。当它作为ASP管道的一部分引发时,代理唯一收到的通知是这是事务的一部分。源或事件内执行的方法是代理默认情况下很少检测的内容。 我希望我们能够为您提供更多的见解。.NET应用程序中有很多移动部件,其中一些涉及操作系统本身、IIS、.NET的版本、方法是否异步、应用程序池设置、执行模式、权限等。 虽然我不想在这里再次引发问题,但这也引起了500错误缺少堆栈跟踪的问题。代理在提供和/或可用时提供堆栈跟踪。如果堆栈跟踪(如果存在)发生在ASP管道内的位置非常重要。有时它会在执行任何实际应用程序代码之前发生。在这种情况下,错误报告给应用程序,然后让.NET代理看到并报告发生了错误,但没有提供其他详细信息。代理只是看到它发生了,并尽可能提供尽可能多的信息。除此之外,代理无法提供更多的详细信息。

我们已经放弃了,所以我很想知道你是否能够解决它!


0

AcquireRequestState 还被 Profile 模块 使用。您尝试禁用该模块了吗?

<modules>
   <remove others unwanted modules... />
   <remove name="Profile" />
</modules>

0

我曾经遇到过同样的问题。我有很多并发的ajax请求,它们都使用存储在ASP.NET ClaimsIdentity中的变量,这实际上是使用SessionState。这意味着,很多服务器响应时间只是在等待SessionState被解锁。

我通过减少锁定轮询间隔来解决了这个问题:

var sessionStateModuleType = typeof(SessionStateModule);
var pollingIntervalFieldInfo = sessionStateModuleType.GetField("LOCKED_ITEM_POLLING_INTERVAL", BindingFlags.NonPublic | BindingFlags.Static);
pollingIntervalFieldInfo.SetValue(null, 30); // default 500ms
var pollingDeltaFieldInfo = sessionStateModuleType.GetField("LOCKED_ITEM_POLLING_DELTA", BindingFlags.NonPublic | BindingFlags.Static);
pollingDeltaFieldInfo.SetValue(null, TimeSpan.FromMilliseconds(15.0)); // default 250ms

上述解决方案在这篇博客文章中被披露。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接