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

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

因此,我们正在对外部公司开发的 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);
    }        
}

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

仍然不确定如果删除 static 关键字,这是否会是个问题。实例每次请求后都处理吗?

答案1

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

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

正如您所说,Application 或 Session 对象的滥用也可能是一个原因。

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

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

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

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

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

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

答案2

内存泄漏,一般来说,是编码逻辑的负面/意外结果,它没有正确(或根本没有)释放其未使用(或不再使用)的资源,同时仍为新的/持续使用/处理要求保留额外资源。总体资源“足迹”随后继续增长,即使实际需求不一定会增加,如果正确利用和释放资源的适当“清理”到位。

简而言之,它不仅限于逻辑编程“滥用”,它可能来自于对资源管理的错误假设或者仅仅是缺乏资源管理。

相关内容