我们的网站出现问题,看似随机(每天左右,最多每 7-10 天一次),网站就会变得没有响应。
我们在 Azure 上有两个 Web 服务器,并且使用 Redis。
我已经成功运行 DotNetMemory 并在崩溃时捕获它,并且我观察到在事件处理程序泄漏
下有两个项目在网站停止工作之前似乎增加了数千个。这两项是 CaliEventHandlerDelegateProxy
和 ArglessEventHandlerProxy
。一旦站点崩溃,我们会收到大量 Redis 异常,无法连接到 Redis 服务器。根据 Azure 门户,我们的 Redis 服务器负载在高峰时段从未超过 10%,并且我们正在遵循所有最佳实践。
我花了很长时间浏览我们的网站,确保没有明显的内存泄漏,并修补了一些未被注意到的案例。有趣的是,这些似乎稍微提高了网站的稳定性。我们检查过的事情:
- 所有 iDisposable 对象现在都包装在 using block 中(我们之前严格执行过此操作,但我们确实发现了一些未正确处理的对象)
- 事件处理程序已取消订阅 - 我们的代码库中很少
- 我们大量使用 WebUserControls。每个页面都将当前母版页作为参数传入。我们已经删除了对此的依赖,因为我们认为它可能导致 GC 不收集页面
我们的最新问题是,当 Web 服务器运行良好,但随后我们运行 DotNetMemory 并将其附加到 w3wp.exe 进程时,它会导致 CaliEventHandlerDelegateProxy
和 ArglessEventHandlerProxy
事件泄漏量迅速增加,直至网站崩溃!因此,只需运行 DotNetMemory 即可重现崩溃。这是我们看到的屏幕截图:
我现在不知所措,我相信我已经用尽了代码库中内存泄漏的所有可能性,我们的“解决方案”是让应用程序池每隔几个小时回收一次,以确保安全。
我们甚至尝试将 Redis 升级到高级层,甚至将网络服务器上的所有驱动器升级为 SSD,看看它是否能帮助解决看似没有的问题。
谁能解释一下可能导致这些问题的原因吗?
最佳答案
All iDisposable objects are now wrapped in using blocks (we did this strictly before but we did find a few not disposed properly)
在没有任何相关信息的情况下,我们不能对崩溃说太多,但我对此有一些猜测。 我看到 10 000 (!) 未处置的对象由终结队列处理。让我们从它们开始,找到所有这些并在您的应用程序中添加 Dispose 调用。 另外,我建议检查您的应用程序使用了多少系统句柄。操作系统对句柄数量有限制,如果超过,则无法创建更多文件句柄、网络套接字等。我特别推荐它,因为未处理的对象数量很多。
此外,如果您在访问 Redis 时超时,请获取性能分析器并查看原因。我建议使用 JetBrains dotTrace 并使用 TIMELINE 模式来获取应用程序的配置文件,它将显示线程休眠、线程争用以及更多信息,这些信息将帮助您找到问题根源。您可以使用命令行工具来获取配置文件数据,以免在服务器端安装GUI应用程序。
it causes the CaliEventHandlerDelegateProxy and ArglessEventHandlerProxy event leaks to increase rapidly
dotMemory 不会更改您的应用程序代码,也不会在分析进程中分配任何托管对象。 Microsoft Profiling API 将一个 dll(用 C++ 编写)注入(inject)到分析过程中,它是 dotMemory 的一部分,名为 Profilng Core,扮演“服务器”的角色(其中用 C# 编写的独立 dotMemory 是客户端)。分析核心在将收集的数据发送到客户端之前对其进行一些处理,它需要一些内存,当然,这些内存是在分析过程的地址空间中分配的,但它不会影响托管内存。
内存分析可能会影响应用程序的性能。例如,当应用程序进行分析时,分析 API 会禁用并发 GC,或者内存分配数据收集会显着降低应用程序的速度。 为什么您认为 CaliEventHandlerDelegateProxy 和 ArglessEventHandlerProxy 仅在 dotMemory 分析下分配?您能描述一下您是如何探索这一点的吗?
Event handlers are unsubscribed - there are very few in our code base
dotMemory 将事件处理程序报告为泄漏,这意味着只有一个对它的引用 - 从事件源,无法取消订阅此事件。检查所有这些泄漏,通过查看代码找到您的泄漏是如何发生的。无论如何,这些对象只保留了 110.3 KB,为什么您认为您的网站会因为它们而崩溃?
I'm at a loss now, I believe I've exhausted all possibilities of memory leaks in our code base
在内存消耗增长的一段时间内拍几张快照,打开其中一些快照的完整比较,查看所有不应该存活的存活对象,找出它们存活的原因。这是证明您的应用没有内存泄漏的唯一方法,查看代码并不能证明这一点,抱歉。
希望如果您执行我建议您执行的所有事件(性能分析、完整快照和快照比较调查,不仅仅是检查 View ,检查为什么存在大量未处理对象),您将找到并解决根本问题.
关于asp.net - CaliEventHandlerDelegateProxy 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59984317/