我们有一个 CF8 应用,在负载高达 1200 人时,该应用可运行 20-25 分钟,然后崩溃。此负载由我们的负载测试工具生成:1200 名用户在 5 分钟内加速(我们用户的近似行为),运行一小时。
我们在 Solaris 10、Apache 2、JRun 4 和 Oracle 10g 上安装了此应用程序。Java 版本是 1.6。
在初始负载测试期间,线程转储指向指向会话的监视器死锁。
"jrpp-173":
waiting to lock monitor 0x019fdc60 (object 0x6b893530, a java.util.Hashtable),
which is held by "scheduler-1"
"scheduler-1":
waiting to lock monitor 0x026c3ce0 (object 0x6abe2f20, a coldfusion.monitor.memory.SessionMemoryMonitor$TopMemoryUsedSessions),
which is held by "jrpp-167"
"jrpp-167":
waiting to lock monitor 0x019fdc60 (object 0x6b893530, a java.util.Hashtable),
which is held by "scheduler-1"
我们增加了会话数量(相对于 CPU 数量,从 32 个 CPU 增加到 48 个同时线程),死锁问题就解决了。虽然改变同时线程数量对响应时间有一点帮助,但 CF 服务器在 20-25 分钟内仍然处于瘫痪状态全部这些测试。
我们运行了更多的线程转储,并看到一个线程锁定了一个监视器,例如:
"jrpp-475" prio=3 tid=0x02230800 nid=0x2c5 runnable [0x4397d000]
java.lang.Thread.State: RUNNABLE
at java.util.HashMap.getEntry(HashMap.java:347)
at java.util.HashMap.containsKey(HashMap.java:335)
at java.util.HashSet.contains(HashSet.java:184)
at coldfusion.monitor.memory.MemoryTracker.onAddObject(MemoryTracker.java:124)
at coldfusion.monitor.memory.MemoryTrackerProxy.onReplaceValue(MemoryTrackerProxy.java:598)
at coldfusion.monitor.memory.MemoryTrackerProxy.onPut(MemoryTrackerProxy.java:510)
at coldfusion.util.CaseInsensitiveMap.put(CaseInsensitiveMap.java:250)
at coldfusion.util.FastHashtable.put(FastHashtable.java:43)
- locked <0x6f7e1a78> (a coldfusion.runtime.Struct)
at coldfusion.runtime.CfJspPage._arrayset(CfJspPage.java:1027)
at coldfusion.runtime.CfJspPage._arraySetAt(CfJspPage.java:2117)
at cfvalidation2ecfc1052964961$funcSETUSERAUDITDATA.runFunction(/app/docs/apply/cfcs/validation.cfc:377)
正如您在上文最后一行中看到的,有多个引用 CFM 和 CFC,并且这些行具有“cflock”标签,其范围为“应用程序”。然后,我们(开发团队)将它们的范围更改为“名称”。
经过更多负载测试后,不再出现锁定,也不再出现死锁,但现在应用程序会在 7-10 分钟内崩溃。
我们从各自的管理员那里获得了系统、网络和数据库报告,并且它们没有被征税;甚至使用服务器监视器、top、prstat、运行 sar 报告等查看了服务器统计信息。所以我们相信这是 CF 服务器或可能是 JVM 的问题。
我不知道我们还能尝试什么。免责声明:我不是 CF 开发人员或管理员。我只是在运行负载测试、分析报告、线程等,并与开发和管理团队分享结果,并尝试下一个更改,等等。到目前为止还没有成功。
有人遇到过类似的事情吗?你是如何进行诊断和故障排除的?欢迎提出各种想法和建议。
感谢您的时间!
知识管理
答案1
当您锁定应用程序范围(名称或“范围”锁定)时,您实际上是在“序列化”应用程序变量。因此,这本身就是一个问题……应用程序变量应该被锁定并写入一次,然后随意读取(最好在没有锁定的情况下安全地读取,因为它们不会改变)。无论如何,这可能是一个转移注意力的借口。当您锁定应用程序范围并一直访问您的锁定时,您自然会在日志中得到与其相关的内容(因为那里发生了很多事情)。
这是我最好的猜测
检查“coldfusion 监视器”,并确保(两次、三次、四次)“内存分析”未启用。事实上,对于您的负载测试,请确保未启用跟踪和监视 - 我甚至会关闭指标。上面的代码片段让我认为内存跟踪已打开,而您只是在超载服务器。发生这种情况是因为必须不断检查堆是否有变化 - 非常昂贵。当您进行基准测试时,内存跟踪应该只启用一小段时间。
32 个 CPU 和 48 个模拟请求.... 那是很大的 CPU 能力。如果您使用 JRUN,请确保 Jrun 线程设置得足够远,以便 Jrun 有一些控制线程可以使用。
检查 bin 目录中是否存在热点错误 - 以“hs_errpidXXX.log”(或类似内容)开头的错误。如果您看到它们,堆栈可能会给您一些线索 - 但通常是内存不足错误或第三方 CFX 或本机 java 代码之类的东西,它们会向 hotsport 编译器抛出未处理的异常。
最后,仔细检查您的客户端变量。有时您在使用它们时“并不认为”您正在使用它们。如果确实如此,它们将存储在 Solaris 服务器上的文件中,这肯定会在负载下导致问题 - 尤其是在清除期间将文件附加到或锁定时。查看此帖子了解更多信息:
http://www.coldfusionmuse.com/index.cfm/2009/10/27/registry.bad.datasource.good
目前我想到的就这些...如果您希望我周一(正式)仔细研究一下,请告诉我,我们可以聊聊。
答案2
感谢 Mark 和 Adam 花时间查看我的问题并提出建议。此特定问题已得到解决。显然,我们的新服务器是基于一台“损坏的 CF”旧服务器构建的——无论这意味着什么。它已经重新构建,性能不再是问题。
知识管理