我正在对JBoss中部署的Web应用程序进行一些负载测试。它开始很好,但随着测试的增加和更多模拟用户开始使用JBoss,性能严重下降:
Resposne time chart http://i46.tinypic.com/2mob2f9.jpg
将VisualVM连接到它,我可以看到线程都很好,然后突然开始花大部分时间等待监视器(绿色正在运行,红色是监视器,黄色正在等待):
Thread state graph http://i46.tinypic.com/105v6lk.jpg
运行jstack,我看到线程都在同一个地方等待:
"http-0.0.0.0-8080-172" daemon prio=6 tid=0x000000005da90000 nid=0xd2c waiting for monitor entry [0x000000006cb4e000] java.lang.Thread.State: BLOCKED (on object monitor) at org.apache.log4j.Category.callAppenders(Category.java:185) - waiting to lock (a org.apache.log4j.spi.RootCategory) at org.apache.log4j.Category.forcedLog(Category.java:372) at org.apache.log4j.Category.debug(Category.java:241) [my code]
大多数~200个HTTP处理器线程正在等待同一个监视器。查看WAR的log4j.xml,它为CONSOLE提供了一个appender设置。我删除了appender并再次尝试我的测试。相同的行为,除了jstack显示在不同的地方等待的所有线程:
"http-0.0.0.0-8080-251" daemon prio=6 tid=0x0000000059811800 nid=0x1108 waiting for monitor entry [0x0000000073ebe000] java.lang.Thread.State: BLOCKED (on object monitor) at java.util.Hashtable.get(Hashtable.java:333) - waiting to lock (a org.jboss.util.property.PropertyMap) at java.util.Properties.getProperty(Properties.java:932) at org.jboss.util.property.PropertyMap.getProperty(PropertyMap.java:626) at java.lang.System.getProperty(System.java:653) at org.jaxen.saxpath.helpers.XPathReaderFactory.createReader(XPathReaderFactory.java:109) at org.jaxen.BaseXPath.(BaseXPath.java:124) at org.jaxen.BaseXPath.(BaseXPath.java:153) at nu.xom.JaxenConnector.(JaxenConnector.java:49) at nu.xom.Node.query(Node.java:424) [my code]
什么都不做,我重新启动JBoss,运行测试,然后一旦它变慢就运行jstack。所有线程都在另一个地方等待:
"http-0.0.0.0-8080-171" daemon prio=6 tid=0x000000005d0d1000 nid=0x15d4 waiting for monitor entry [0x000000006cb4e000] java.lang.Thread.State: BLOCKED (on object monitor) at sun.nio.cs.FastCharsetProvider.charsetForName(FastCharsetProvider.java:118) - waiting to lock (a sun.nio.cs.StandardCharsets) at java.nio.charset.Charset.lookup2(Charset.java:449) at java.nio.charset.Charset.lookup(Charset.java:437) at java.nio.charset.Charset.isSupported(Charset.java:479) at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:49) at java.io.InputStreamReader.(InputStreamReader.java:57) at java.io.FileReader.(FileReader.java:41) [my code]
到底发生了什么事?我过去使用过jstack,当事情运行正常并得到预期的结果时我尝试运行它。我认为jstack很好。什么可能导致这种奇怪行为的想法?关于从哪里去的任何想法?
答案 0 :(得分:3)
这种行为是可以预期的。当您扩展负载测试时,您总是会发现瓶颈,而在复杂的系统中,这些瓶颈会随之转移。
您的工作是确定这些瓶颈,并尝试一次修复一个瓶颈。每次你这样做,你总会找到另一个,但希望系统每次都能更好地扩展。这并不容易,但随后缩放负载并不容易。
拿你的第一个例子。你有很多调用log4j的Logger.debug()
方法。 Log4j在负载下记录时性能不佳,因此您需要采取一些预防措施。即使你的log4j配置说“不记录DEBUG消息”,log4j仍然需要做一些工作才能实现这一点。建议的处理方法是在Logger.debug()
{Logger.debug();阻止。这应该改变这个特定的瓶颈。
在您的2示例中,您正在调用XOM的if Logger.isDebugEnabled()
方法。此方法必须在每次调用时重新编译XPath表达式,这似乎是一个瓶颈。找到一个API,您可以在其中预编译XPath表达式并重新使用它。
在第3个示例中,您正在阅读Node.query()
。这在高负载系统中不是一个好主意,当你进行大量小型操作时,file-io很慢。如果可以的话,考虑重新实现这个以不同的方式工作。
所有这些都是无关的,但是在缩放负载时您会看到所有当前的性能瓶颈。你永远不会完全摆脱它们,但希望你可以把它弄到足够好的程度。
答案 1 :(得分:2)
我在运行Eclipse的Tomcat中设置应用程序并没有看到问题。最终我发现我们使用32位Windows服务包装器启动JBoss,即使我们使用的是64位JDK。这台机器是64位的。我不确定这怎么会起作用?无论如何,改成32位JDK会导致疯狂的问题消失,我能够继续我的生活。