我们的记忆问题已经很久了。我终于找到了如何复制这个问题,但我不知道是什么导致了它或如何解决它。
我们在 Web 可访问的 /controller 目录中有许多 cfc,用于处理提交和处理。当不带方法参数直接调用 cfc 时,服务器开始占用内存。
例如,像http://www.domain.com/controller/LoginController.cfc这样的 URL将在浏览器中运行,直到超时。/CFIDE 已被锁定,无法公开访问
所以 cfexplorer 不(或不应该)可用。
我们使用 FusionReactor 来监控我们的实例。我们的服务器设置为 20GB 的堆空间。在加载应用程序后重新启动时,内存将在 800MB 左右徘徊。
在正常流量下,内存将在 5GB 和 10GB 之间波动,并定期进行垃圾收集。一段时间后,服务器最终达到 98% 的容量。它倾向于在那里运行
有时可以持续数小时甚至数天,直到某些流量高峰将其推倒并发生内存不足错误。垃圾回收没有恢复内存,也没有活动
FusionReactor 报告的长时间运行的线程。只有重新启动服务器才能恢复它。
使用 FusionReactor(我们刚刚安装了它,这就是我最终了解这个问题的方式)我正在检查 PermGen 内存空间,发现它占了
85% 的堆。这似乎根本不对。我执行了一次内存转储并通过 Eclipse 将其加载到 MAP 中进行分析。我发现内存中有10个对象
测量 1.7GB(1.7x10 约为总堆的 85%)。这些对象如下所示:
Class Name | Shallow Heap | Retained Heap | Percentage
byte[1769628928] @ 0x4d963b198 ...128.................POST......../controller/LoginController.cfc......../controller/LoginController.cfc........173.14.93.66........173.14.93.66........www.domain.com........443........HTTP/1.1.......;D:\websites\domain\system\controller\Lo...| 1,769,628,944 | 1,769,628,944 | 8.60%
所以我在我们的一台服务器上重新启动了 CF。检查了 FusionReactor 并没有看到内存使用情况。然后转到浏览器并首先像这样调用cfc:
http://www.domain.com/controller/LoginController.cfc?method=foo
这导致 onMissingMethod 处理程序正确启动并重定向到适当的错误页面,而没有服务器影响。
但是然后调用这个:
http://www.domain.com/controller/LoginController.cfc
导致页面挂起。FusionReactor 报告没有活动请求,即使一个正在运行,这就是为什么我们无法在问题发生时识别问题。更糟糕的是,刷新内存会发现它缓慢增加了十分之一的百分比,而没有报告任何活动。服务器上的超时设置为 5 分钟。我假设它最终会被杀死,然后在 1.7GB 时成为孤儿。这并没有导致服务器宕机,只是增加了它现在运行的内存,其使用量仅为 3GB,垃圾收集无法恢复任何东西。这似乎可以解释为什么随着时间的推移,对这些 URL 的随机调用会慢慢地消化并保留内存。
接下来,我从多个浏览器选项卡中调用了 URL。这几乎瞬间将内存飙升至 98%。FusionReactor 现在显示两个长时间运行的请求 10 秒并且即使有超过 15 个浏览器选项卡在运行,它也在攀升。强制杀死线程似乎无济于事。只有重新启动服务器才能解决问题。
所以现在我已经明确地确定了这个问题(幻象线程在 PermGen 堆中创建了巨大的孤立对象)以及如何复制这个问题。
我不知道如何或为什么直接向 cfc 提出请求。可能是机器人或偶尔奇怪的浏览器行为。
所有巨大的对象都是 jrun.servlet.jrpp.ProxyEndpoint 的实例。
具体是什么导致了这个问题,我该如何解决。
这是运行 Java 1.7.0_25 的 Win2003 服务器上的 CF9.01 标准。
谢谢!