ASP.NET Request.Form 性能

11

我使用了 HttpHandler 来实现一个轻量级的、针对高性能的 Web 服务。 它需要使用内容类型为 application/x-www-form-urlencodedPOST 请求。该 Web 服务执行许多任务,包括解密、数据库工作、业务逻辑等等。在负载测试期间,性能监视器(ANTS 和 Visual Studio)指向了一行代码,它占用了大部分时间,实际上是 67%。

string value = context.Request.Form[MY_FORM_KEY];

在这行代码的调用栈底部,性能监视器显示了这个调用:

System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest();

罪魁祸首是什么?

有人可以帮忙解释一下吗?这个应用程序使用的是 .Net 4,在 Windows Server 2008 上以发布方式运行在 IIS 7 上。

谢谢, Joey J. Barrett


4
如果瓶颈在于Request.Form的索引器,我会感到非常惊讶。与您所描述的所有工作相比,这应该是微不足道的。 - Darin Dimitrov
1
你可能过多地引用了context.Request.Form,相反...你可能需要将值克隆到本地变量中。 - Ahmed Khalaf
1
考虑将其作为标头发送,而不是表单变量。我怀疑Form集合有更多的值,并且获取它会使调用变得笨重。另外,在构建解决方案时,您可以检查目标CPU吗?有时将其更改为x86会消除System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest()周围的瓶颈... - sajoshi
3个回答

6
时间延迟是因为IIS尝试从客户端读取请求流以检索表单值。这个流受到客户端连接的影响,在某些情况下甚至不会返回。我曾经见过Request.Form阻塞超过5分钟的情况,这将导致IIS最终抛出ThreadAbortException。
在我们的情况下,我们有一个HttpModule,必须读取Request.Form值(或者request["key"]也会遍历表单值),它会在服务器上随机阻塞,并永远不会返回。我使用这个HttpModule来跟踪服务器端应用程序性能,这让我意识到,我使用这个模块跟踪的任何内容都将依赖于客户端的连接性,这将扭曲我的服务器端执行结果。
要解决这个问题,您可以在应用程序前面安装反向HTTP代理。反向代理将卸载读取客户端流(并在您的应用程序中阻塞昂贵的线程)的责任,并将完整的请求发送到您的服务器。这将减轻您的应用程序负担,因为您可以将宝贵的应用程序线程保存用于处理主要工作负载,而不是将它们阻塞在读取客户端流上。
此外,您可以卸载HTTPs、负载平衡,甚至在反向代理上缓存一些静态内容(具体取决于您使用的代理)。

2

The

System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest()

这是一个导入的IIS函数(你可能已经猜到了)。由于http.sys是IIS中执行所有http工作的非托管代码,所以在某个时刻,您的应用程序将需要与其通信,但不是直接通信。

我猜正在发生的是,当您读取表单集合时,.net正在从IIS的原始请求中读取它。如果证明它是瓶颈,我建议重构您的代码以异步方式读取表单数据,并将您需要的值存储在本地数据结构中。

西蒙


0

MgdSyncReadRequest 方法阻塞了内部的非托管-IIS API。但引发了托管的 ThreadAbortException
这意味着另一个托管线程可能调用了 Thread.Abort()

我在 referencesource 中搜索,找到了 "RequestTimeoutManager":

http://referencesource.microsoft.com/#System.Web/RequestTimeoutManager.cs,177

thread.Abort(new HttpApplication.CancelModuleException(true));

解决方案(非检查,可能是):通过基于异步的读取器实现,并手动处理超时...

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