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

Cod*_*key 6 windows iis asp.net iis-7.5

IIS/Windows 2008 R2 中的 .Net OutOfMemoryExceptions 在被命中的应用程序的随机页面上抛出的奇怪情况。

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

由于相同的代码可以在旧服务器上运行并且永远不会抛出内存不足异常,因此我们推迟了花费大量时间来分析应用程序和检查转储以及执行有助于避免大对象堆碎片的代码优化(因此我们希望得到一些提示在可能的服务器配置问题上,这可能是罪魁祸首,而不是查看代码库并对其进行优化......)。

配置 1 - Rackspace CloudSites(共享主机,我们只能通过 FTP 访问它,不能访问 IIS 设置):

1 个 IIS 服务器,我们无法控制管理它,但被告知每个应用程序池有 250MB 的回收限制。在我们的 1000 个站点中,许多站点(20-50 左右)显然共享相同的应用程序池。我们从来没有在这里遇到过 OutOfMemoryExceptions 并且多年来一直在其上运行应用程序。

配置 2 - Rackspace 专用服务器(完全控制):

拥有 128GB RAM 的 Monster 服务器,专用,每个站点都有自己的应用程序池。所有应用程序池都具有相同的设置(350MB 回收限制)。不确定这是否有影响,但此服务器上的页面文件大小为 4GB(不知道 Config 1 有什么 - 这是否需要增加/解决?)。

两个配置都在 2 或 3 个 Web 服务器之间进行负载平衡,但这本身并不重要,因为我们看到的站点没有流量,因为 OutOfMemoryExceptions 被杀死。

Mat*_*sen 11

这篇文章在我写的时候升级了,这是外卖的子弹

TL; 博士

  1. 增加页面文件的大小(从臀部拍摄我会说至少 40GB,如果您能负担得起磁盘容量和 I/O,则更多,但请阅读底部的文章)
  2. 增加frequentHitThresholdfrequentHitTimePeriod值(查看 Web 服务缓存性能计数器并相应调整)
  3. maxResponseSize值降低到 85KB 或以下,以避免在大对象堆中缓存条目
  4. 降低应用程序池回收的内存限制,没有多大意义
  5. 考虑将应用程序池中具有相同或相似代码库的应用程序分组

原答案

不确定这是否有影响,但此服务器上的页面文件大小为 4GB(不知道 Config 1 有什么 - 这是否需要增加/解决?

这个,^就在这里^看看吧。

我敢打赌,这正是您的应用程序OutOfMemoryException在响应看似最随机和最良性的请求时抛出 a 的原因,但要了解原因,让我们弄清楚一件事:

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

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

内存管理 101

当一个进程从操作系统分配内存时,它会进入一系列称为pages的片段,每个 4 KB,进程可以将其视为自己的(这通常称为虚拟地址空间)。

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

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

IIS 7.x 如何发挥作用

正如最近在此答案中解释的那样,IIS 还将尝试在为您的应用程序提供服务的同一进程中尽可能多地存储可缓存的输出对象(例如高达 256KB 的静态文件)-除了该答案中的建议之外,您也可以尝试使用<serverRuntime>配置元素调整缓存频率阈值。

在任何情况下,IIS 7.5 - 在其默认配置中 - 非常关心为其工作进程分配足够的内存,即使使用“NO TRAFFIC”,看到工作进程在启动时声明前 100MB 的情况并不少见,即使磁盘上稍小的应用程序代码库。

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

不需要研究生水平的数学就能看出 100MB * 1000 个进程与操作系统必须提供的 128GB RAM 相差不远。即使 IIS 尝试根据需要为其工作进程分配尽可能多的内存,它也会在某个时间点停止,以在安装的总内存的 85% 左右为操作系统留出一些空间,无论可能有多少兆或千兆字节的 RAM是(这不是我见过的文档的事实,而是从具有不同硬件规格的大量 IIS 安装的第一手经验中得出的)。

此时,操作系统可以通过从页面文件中分配页面来帮助释放内存 - 页面存储在物理磁盘上的文件中。由于磁盘容量通常充足,分配大块磁盘存储并不是什么大事,但如果它需要为 1000 个进程分页内存并且只允许在 4GB 的空间上这样做,用不了多久进程将无法分配更长的非碎片内存序列和粉扑!:进程抛出一个OutOfMemoryException,这只是意味着它无法在其可访问的虚拟地址空间中找到足够的相邻页面。

它甚至不必是大对象。它们只需要大于运行时可用的最大连续页面数。从理论上讲,您可能会因为尝试将单个字符附加到当前大小超过 2KB 的字符串而获得 OutOfMemory 异常。

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

微软对这个问题的回答一直是:“看情况”,但至少 1 x RAM + 257MB(这是系统能够写入完整内存转储所需的存储量)。

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

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

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


Bro*_*ley 1

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

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

您不必修改页面文件设置,该设置仅在 128GB RAM 耗尽时使用。

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

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

对 IIS 7.x 应用程序池中的本机内存泄漏进行故障排除