禁用ASP.NET HttpHandler响应缓存

Kev*_*lin 18 asp.net caching httphandler servicestack nancy

背景

我正在比较在IIS 7下运行的NancyFx和ServiceStack.NET的性能(在Windows 7主机上进行测试).两者都非常快 - 在本地测试每个框架进程超过10,000 req/sec,ServiceStack的速度提高了约20%.

我遇到的问题是ASP.NET似乎正在缓存来自HttpHandler的每个唯一URI请求的响应,很快导致大量内存压力(3 GB以上)和垃圾收集器过度工作(大约25%的时间消耗GC).到目前为止,我一直无法禁用对象的缓存和构建,并且正在寻找有关如何禁用此行为的建议.

细节

请求循环基本如下:

for i = 1..100000:
    string uri = http://localhost/users/{i}
    Http.Get(uri)
Run Code Online (Sandbox Code Playgroud)

响应是一个简单的JSON对象,格式为{UserID:n}.

我已经破解了打开的WinDBG,并且每个请求都有:

  • System.Web.FileChangeEventHandler
  • System.Web.Configuration.MapPathCacheInfos
  • System.Web.CachedPathDatas
  • System.Web.Caching.CacheDependencys
  • System.Web.Caching.CacheEntrys

显然,这些缓存项目让我相信它是一个缓存膨胀问题(我很想摆脱150,000个无法使用的对象!).

到目前为止我尝试过的

  • 在IIS的"HTTP Resonse Headers"中,将"Expire Web content"设置为"Immediate".
  • 在web.config中

    <system.web>
     <caching>
        <outputCache enableOutputCache="false" enableFragmentCache="false"/>
      </caching>
    </system.web>
    
    Run Code Online (Sandbox Code Playgroud)
  • 同样在web.config中(以及策略的许多变体,包括无).

    <caching enabled="false" enableKernelCache="false">
      <profiles>
        <add policy="DontCache" kernelCachePolicy="DontCache" extension="*/>
      </profiles>
    </caching>
    
    Run Code Online (Sandbox Code Playgroud)
  • 查看框架的源代码,看看是否可能存在使用ASP.NET缓存的任何"功能".虽然有缓存帮助程序,但它们对框架本身是私有的,并且似乎不利用ASP.NET缓存.

更新#1

通过反射器挖掘我发现将值设置UrlMetadataSlidingExpiration为零消除了过多内存使用的大部分,代价是将吞吐量减少50%(FileAuthorizationModule类缓存FileSecurityDescriptors,生成时必须有些昂贵,UrlMetadataSlidingExpiration是非零).

这是通过更新web.config并将以下内容放入:

<hostingEnvironment urlMetadataSlidingExpiration="00:00:00"/>
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我将尝试完全禁用FileAuthorizationModule运行,看看是否有帮助.但是,ASP.NET仍然会生成2*N MapPathCacheInfoCacheEntry对象,因此内存仍在消耗,速度要慢得多.

更新#2

另一半问题与此处描述的问题相同:阻止许多不同的MVC URL填充ASP.NET缓存.设置

<cache percentagePhysicalMemoryUsedLimit="1" privateBytesPollTime="00:00:01"/> 有帮助,但即使有这些非常激进的设置,内存使用量也会快速上升到2.5GB(相比之下为4GB).理想情况下,这些对象永远不会首先创建.如果做不到这一点,我可能会采用一种使用反射来清除缓存的hacky解决方案(所有这些条目都是"私有的",并且在迭代公共缓存时不会枚举).

Fra*_*mas 1

确保 IsReusable 属性设置为 false,以便 IIS 不会重复使用同一请求进程来处理该请求。

http://support.microsoft.com/kb/308001