我们正在运行一些 X64 Win Server 2012 网络服务器(所以是 IIS 8)。
我们注意到,这些盒子上的可用内存始终保持在 5-10% 的水平。实际上,我们在这些盒子上运行了相当多的应用程序(13 个站点,13 个应用程序池中的 80 个应用程序)。由于它们对应于不同的数据库和物理站点,因此每个站点的大部分代码都是重复的,但应用程序是相同的。
由于内存不断增长,我们确信应用程序中存在内存泄漏,因此我们立即着手解决这一问题,但我对 IIS 的内存分配和管理感到困惑。我想知道 IIS 8 或 x64 服务器是否有任何不同(我们最近刚刚迁移到 x64)。
因此,基本上我们的每个 Web 服务器都有 6GB 内存,并且会占用 5-10% 的可用内存。我们确定泄漏的顶级应用程序使用了高达 1.2GB 的内存。下一个约为 800MB,其余的平均约为 400-500MB(所有这些值都是私有内存,如任务管理器中所示)正如我所说,代码是重复的,因此如果一个站点发生泄漏,那么所有站点都会发生泄漏,只是不同的物理位置可以打开或关闭某些功能,这解释了巨大的差异。
在解决问题的同时,我们决定只增加内存,这样我们就不会遇到问题。所以昨晚我关闭了每台服务器,并将内存翻倍至 12GB。今天早上,这 3 台服务器的内存使用率分别为 77%、80% 和 82%。所有进程的内存使用率都增加了 1.5-2 倍。
所以现在我很困惑。这真的是内存泄漏吗?还是存在某种内存预分配?或者它永远不会释放内存,除非另一个进程像 SQL Server 那样请求它?
如果内存翻倍后内存突然变得如此之大,那么是什么让内存水平保持在 6GB 呢?是否设置了阈值?IIS/ASP 是否只是在内存不足之前不进行垃圾回收,还是其他原因?
任何答案都将受到赞赏。
答案1
别担心!你可能只是缓存过多了!
IIS 中的默认输出缓存配置同时启用内核模式和用户模式缓存。
内核模式缓存由本机 HTTP 驱动程序(又名 http.sys)管理,速度极快,但只能提供“公开”的内容,因为它需要能够在请求到达 Web 应用程序之前响应缓存命中。
不幸的是,这意味着许多请求类型无法在内核模式下缓存,包括授权会话(例如访问需要身份验证的网站)。
您描述的设置类型听起来像是某种多租户客户端服务,这让我相信内核模式缓存已经不存在了。
另一方面,用户模式缓存在应用程序级别进行管理,缓存对象存储在服务工作进程的内存集中。总缓存大小maxCacheSize
由system.webServer/Caching
配置元素。
默认情况下,该maxCacheSize
属性设置0
为让 IIS 分配当前允许的尽可能多的内存。
如果你有很多连续的小 (<256kb) 命中,但低uri 缓存命中率,IIS 肯定会吃掉你提供的所有内存。
maxCacheSize
您可以通过降低值或完全禁用服务器上的输出缓存来轻松测试这是否正确。
如果您仍然确信应用程序存在内存问题,请启动性能监视器并查看“ASP.NET 应用程序”性能计数器对象。
选择 GC 计数器并查看垃圾收集如何分散。
Gen0 收集应该代表几乎所有的处置,而大量的 Gen1 和 Gen2 收集可能表明对象生命周期过长 - 这是内存管理失败的常见症状