IIS7.5应用程序池回收 – .Net OutOfMemoryException

在.NET / Windows 2008 R2中发生.Net OutOfMemoryExceptionexception的情况被抛出到正被命中的应用程序的随机页面上。

我们有大约1000个独立的站点,它们是相同的.Net应用程序(每个站点有不同的代码库文件夹和应用程序池)。 64位Windows并运行.Net 2.0,应用程序编译与“AnyCPU”标志。

由于相同的代码在旧服务器上工作,并且永远不会抛出内存不足,所以我们不再花时间分析应用程序并检查转储和执行代码优化,这有助于避免大对象堆碎片化(所以我们希望得到一些提示在可能的服务器configuration问题,可能是罪魁祸首比在代码库和优化…)。

configuration1 – Rackspace CloudSites(共享主机,我们只能FTP到它,不能访问IIS设置):

1个IIS服务器,我们无法控制pipe理它,但被告知每个应用程序池有一个250MB的回收限制。 在我们的1000个网站中,很多网站(20-50ish)显然共享相同的应用程序池。 我们从来没有在这里得到OutOfMemoryExceptions,并且应用程序运行多年以来。

configuration2 – Rackspace专用服务器(完全控制):

拥有128GB内存的怪兽服务器,每个站点都有自己的应用程序池。 所有应用程序池具有相同的设置(350MB回收限制)。 不知道这是否是结果,但这个服务器上的页面文件大小是4GB(不知道configuration1有什么 – 这是否需要增加/解决?)。

两个configuration在2个或3个Web服务器上都是负载平衡的,但是这本身并不重要,因为我们正在使用NO TRAFFIC来拦截出现OutOfMemoryExceptions的站点。

当我写这篇文章时,这个post升级了,这里是外卖子弹

TL; DR

  1. 增加你的页面文件的大小(从臀部拍摄,至less40GB,如果你能承受磁盘容量和I / O,更多的是读取底部的文章)
  2. 增加frequentHitThresholdfrequentHitTimePeriod值(查看Web服务caching性能计数器并进行相应调整)
  3. 将maxResponseSize值降低到85KB或更低,以避免大对象堆中的高速caching条目
  4. 降低应用程序池回收的内存限制,没有什么意义
  5. 考虑在应用程序池中使用相同或相似的代码库对应用程序进行分组

原始答复

不知道这是否是结果,但该服务器上的页面文件大小是4GB(不知道configuration1有什么 – 这是否需要增加/寻址?

这里,在这里^在这里^看看它。

我敢打赌,这就是为什么你的应用程序抛出一个OutOfMemoryException来回应这个看似最随机和最温和的请求的原因,但是要理解为什么,让我们明白一件事情:

OutOfMemory并不意味着你的服务器内存不足!

我知道这听起来像个不好的笑话,但事实并非如此。 这不是操作系统抱怨内存耗尽 – 这是一个过程。
如果最后的陈述对你没有意义,请继续阅读。

内存pipe理101

当一个进程从操作系统分配内存时,它会产生一个叫做页面的片段序列,每个片断有4千字节,这个进程可以把它视为自己的(这通常被称为虚拟地址空间)。

由于对象(如string,XML文档,图像或任何需要保存在内存中的内容)可能会超过4KB的页面大小,因此进程将需要不时从该内存中分配多个连续的页面。

然而,随着时间的推移,内存空间变得分散,甚至使用.NET CLR。 垃圾收集器将尝试尽其所能帮助您的应用程序更好地使用地址空间,方法是在收集期间重新排列工作集中的页面(这实际上与磁盘碎片整理相同),但指向大对象堆例如,将保持不变。

IIS 7.x如何发挥作用

正如最近在这个答案中所解释的那样 ,IIS也将尝试尽可能多地存储可caching的输出对象(例如最大256KB的静态文件),除了在答案中的build议之外,也可以尝试使用<serverRuntime>configuration元素来调整caching频率阈值。

在任何情况下,IIS 7.5(在其默认configuration中)都非常在意为其工作进程分配足够的内存,甚至在“无stream量”的情况下,看到工作进程在启动时声明第一个100MB并不罕见,即使磁盘上的一个稍小的应用程序代码库。

这与页面文件有什么关系?

不需要研究生水平的math就可以看出,100MB * 1000的进程离OS的128GB内存不远。 尽pipeIIS试图根据需要为其工作进程分配尽可能多的内存,但在某些时候停止为操作系统留出一些空间,大概占安装的总内存的85%,而不pipe有多less兆字节或千兆字节的内存(这不是我见过的文档,而是从大量安装不同硬件规格的第一手经验)。

此时,操作系统可以通过从页面文件中分配页面来帮助释放内存,而不是从物理磁盘上的文件中存储页面。 由于磁盘容量通常很大,因此分配大块磁盘存储并不是什么大问题,但是如果需要为1000个进程分页内存,并且只允许在4GB的空间内进行分页,那么不需要很长时间进程将无法分配更长的非片段化内存和泡泡序列 :该进程抛出一个OutOfMemoryException ,它只是意味着它无法find足够的相邻页面的东西在其可访问的虚拟地址空间。

它甚至不一定是大对象。 它们必须大于运行时可用的连续页面的最大数量。 从理论上讲,你可能会得到一个OutOfMemoryexception,试图将一个字符添加到当前大于2KB的string中。

那么页面文件大小应该设置为?

微软对这个问题的回答一直是:“取决于”,但是至less1 x RAM + 257MB(这是系统要求能够写入完整内存转储的存储量)。

经验法则似乎大约是1.5-2 x RAM,但是又取决于,并且已经发表了许多关于如何在给定系统上确定正确的最小和最大页面文件大小的文章。 我已经包括了最相关的一个在底部。

一定要监视包含页面文件的磁盘,如果磁盘队列长度计数器开始尖峰,您可能需要将其移动到专用磁盘,或者将其分散到多个磁盘上。

如何为64位版本的Windows确定适当的页面文件大小

您可以禁用应用程序池内存限制(将其设置为0)以快速允许您的应用程序池占用尽可能多的所需。 但是,这听起来像是有些东西在泄漏,最终会占用所有可用的内存(并再次回收应用程序池)。

检查您的c:\windows\system32\LogFiles\HTTPERR日志文件中的致命错误消息。

你不应该修改你的PageFile设置,只有在128GB内存耗尽的时候才能使用。

要追踪内存泄漏的来源,您需要使用Trace Logs或DebugDiag进行更多的挖掘(不是最简单的任务):

如何使用IISdebugging诊断工具解决IIS进程中的内存泄漏问题

解决IIS 7.x应用程序池中的本机内存泄漏问题

我们的问题是通过将1000多个应用程序池切换到32位模式而不是默认的64位来解决的。 我们可以通过翻转64位来确认,并立即看到内存exception。

我相信Jessen在页面文件上的观点确实有重量。 。 。 由于加载页面文件需要系统重启,我们试图翻转到32位模式的应用程序池(这不需要重新启动),幸运的。

如果有人对此有一些有趣的评论,请随意!

谢谢!