ASP.NET 应用占用内存。Application/Session 对象的原因是什么?

Nil*_*zor 5 iis-7 asp.net memory-leak

因此,我们正在对由外部公司开发的 ASP.NET 应用程序进行压力测试。我们每秒执行大约 50 个请求,大约半小时后,48 个工作进程 (w3wp.exe) 中的每一个都达到大约 400 MB 并且还在计数。在 IIS7 上运行。

现在,在干预了 dotTrace 之后,我相当肯定这里存在内存泄漏,但是在不了解应用程序的情况下很难 100% 确定。当我们向开发人员提出这个理论时,他们在 30 秒后驳回了它,说“内存在 .NET 中是自动处理的”。如果 .NET 是最终数据,那么肯定会收集 48x~400MB 的垃圾吗?

无论如何,我习惯于使用 WinForms。如何在 ASP.NET 中创建内存泄漏?在 .NET 中(错误地)使用 Application 和 Session 对象是唯一的方法吗?

编辑

自从发布这个问题以来,我了解到在请求处理程序中保存对对象的静态引用(无论是 Web 服务类、Web 表单还是其他)会导致“泄漏”。在这里可能不是正确的术语,但无论如何......这我不确定,因为我认为处理程序类在 IIS 每次请求后都会被杀死并重新创建。

所以代码如下:

public class SomeService : IService
{
    public static List<RequestData> _requestDataHistory = new List<RequestData>();
    public void SomeRequest(RequestData data)
    { 
        _requestDataHistory.Add(data);
    }        
}
Run Code Online (Sandbox Code Playgroud)

迟早会让你的服务器崩溃。也许这对大多数人来说是显而易见的,但对我来说不是:-)

如果您删除了 static 关键字,仍然不确定这是否会成为问题。是否在每次请求后处理实例

Sun*_*nny 2

开发商可能是对的。在 .Net 世界中,垃圾收集和释放内存会在需要时发生。也就是说,如果有足够的内存可供应用程序使用,它可能会消耗越来越多的内存,直到操作系统不允许更多的分配。您不必担心这一点,除非它确实会引起问题。

当然,如果应用程序没有正确处理非托管资源(例如套接字、文件处理程序等),则可能会出现内存泄漏。查看操作系统对象(在任务管理器中,您可以启用句柄和用户对象列)以了解如何他们成长。

正如您所说,应用程序或会话对象误用也可能是一个原因。

我想知道为什么你会有 48 个应用程序池(工作进程)。这太过分了,你根本不需要它。

GC 管理每个进程的内存,每个进程 400MB 根本不算多。将应用程序池的数量减少到nr。核心数 - 1,然后对应用程序进行压力测试。如果它增长太多,您可能会担心内存泄漏。

根据您的附加信息,是的,在这种情况下,历史列表将无限期地增长。静态对象为每个应用程序域创建一次,并一直存在到应用程序域存在为止。

我不建议您随意删除 static 关键字,除非您知道不会破坏某些应用程序逻辑。调查为什么要收集这些数据以及这些数据的用途。该代码还有另一个问题 - 它不是线程安全的,当两个请求同时进入并决定将数据添加到该列表时,它的行为是未定义的。

最好将您的问题转移到 stackoverflow.com,因为这是一个编程问题,而不是管理问题。

如果您无法控制该代码,并且确实想解决内存问题,您可以将应用程序池设置为在 X 次请求后或在获得超过 Y 量的内存后进行回收 - 但同样,这不是一个真正的解决方案。