Java 等待随机监视器的JBoss线程

Java 等待随机监视器的JBoss线程,java,performance,debugging,concurrency,jboss,Java,Performance,Debugging,Concurrency,Jboss,我正在对部署在JBoss中的web应用程序进行负载测试。它的启动很好,但随着测试的进行,越来越多的模拟用户开始使用JBoss,性能会严重下降: 将VisualVM连接到它,我可以看到线程都很好,然后突然开始花费大部分时间等待监视器(绿色为运行,红色为监视器,黄色为等待): 运行jstack时,我看到所有线程都在同一个位置等待: "http-0.0.0.0-8080-172" daemon prio=6 tid=0x000000005da90000 nid=0xd2c waiting for

我正在对部署在JBoss中的web应用程序进行负载测试。它的启动很好,但随着测试的进行,越来越多的模拟用户开始使用JBoss,性能会严重下降:

将VisualVM连接到它,我可以看到线程都很好,然后突然开始花费大部分时间等待监视器(绿色为运行,红色为监视器,黄色为等待):

运行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] “http-0.0.0-8080-172”守护进程prio=6 tid=0x000000005da90000 nid=0xd2c等待监视器条目[0x000000006cb4e000] java.lang.Thread.State:阻塞(在对象监视器上) 位于org.apache.log4j.Category.callAppenders(Category.java:185) -等待锁定(org.apache.log4j.spi.RootCategory) 位于org.apache.log4j.Category.forcedLog(Category.java:372) 位于org.apache.log4j.Category.debug(Category.java:241) [我的代码] 大约200个HTTP处理器线程中的大多数正在等待同一个监视器。查看WAR的log4j.xml,它有一个用于控制台的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] "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] “http-0.0.0-8080-251”守护进程prio=6 tid=0x0000000059811800 nid=0x1108正在等待监视器条目[0x0000000073ebe000] java.lang.Thread.State:阻塞(在对象监视器上) 获取(Hashtable.java:333) -等待锁定(org.jboss.util.property.PropertyMap) 位于java.util.Properties.getProperty(Properties.java:932) 位于org.jboss.util.property.PropertyMap.getProperty(PropertyMap.java:626) 位于java.lang.System.getProperty(System.java:653) 位于org.jaxen.saxpath.helpers.XPathReaderFactory.createReader(XPathReaderFactory.java:109) 位于org.jaxen.BaseXPath。(BaseXPath.java:124) 位于org.jaxen.BaseXPath。(BaseXPath.java:153) 位于nu.xom.JaxenConnector。(JaxenConnector.java:49) 位于nu.xom.Node.query(Node.java:424) [我的代码] 不做任何更改,我重新启动JBoss,运行测试,然后在速度变慢时运行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] "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] “http-0.0.0-8080-171”守护进程prio=6 tid=0x000000005d0d1000 nid=0x15d4等待监视器条目[0x000000006cb4e000] java.lang.Thread.State:阻塞(在对象监视器上) 位于sun.nio.cs.FastCharsetProvider.charsetForName(FastCharsetProvider.java:118) -等待锁定(sun.nio.cs.StandardCharset) 位于java.nio.charset.charset.lookup2(charset.java:449) 位于java.nio.charset.charset.lookup(charset.java:437) 位于java.nio.charset.charset.isSupported(charset.java:479) 位于sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:49) 在java.io.InputStreamReader。(InputStreamReader.java:57) 位于java.io.FileReader。(FileReader.java:41) [我的代码]
到底发生了什么事?我在过去使用过jstack,我试着在一切正常的情况下运行它,并得到了预期的结果。我想jstack很好。你知道什么会导致这种奇怪的行为吗?你有什么想法吗?

这种行为是意料之中的。当您扩展负载测试时,您总是会发现瓶颈,在一个复杂的系统中,这些瓶颈会四处移动

你的工作就是找出这些瓶颈,并试图一次解决一个。每次你这样做,你总会找到另一个,但希望系统每次都能扩展得更好。这并不容易,但是扩展负载也不容易

  • 以你的第一个例子为例。您有很多对log4j的
    Logger.debug()方法的调用。Log4j在负载下记录时性能不佳,因此需要采取一些预防措施。即使您的log4j配置说“不要记录调试消息”,log4j在实现这一点之前仍然需要做一些工作。建议处理的方法是将每个
    Logger.debug()
    调用包装在
    if Logger.isDebugEnabled()
    {Logger.debug();}`块中。这将改变这个瓶颈

  • 在2ndexample中,调用XOM的
    Node.query()
    方法。此方法必须在每次调用时重新编译XPath表达式,这似乎是一个瓶颈。找到可以预编译XPath表达式并重新使用的API

  • 在第三个示例中,您正在读取一个
    文件
    。在高负载系统中,这不是一个好主意,当您执行大量小操作时,文件io会很慢。考虑重新执行这一点,如果可以的话,可以采用不同的方式。


所有这些都是不相关的,但都存在性能瓶颈,您将在扩展负载时看到这些瓶颈。你永远都无法摆脱它们,但希望你能把它做到足够好的程度。

我在Tomcat中设置了应用程序,通过Eclipse运行,但没有发现问题。最终,我发现我们开始使用32位Windows服务包装器启动JBoss,尽管我们使用的是64位JDK。这台机器是64位的。我甚至不知道这是怎么回事?无论如何,改用32位JDK后,疯狂的问题消失了,我可以继续我的生活。

没有更多的上下文/信息,很难说具体发生了什么。一般来说,对于各种资源似乎存在大量争用和/或可能出现死锁情况。作为您的第一步,听起来您删除了一些对log4j的争用。通过缓存查询结果或同步对可能导致死锁的数据结构的访问,是否可以对其他两种资源执行相同的操作?我很乐意提供更多信息,只是不确定提供什么。奇怪的是,尽管存在很多争用,但线程并没有死锁。他们在监视器上等待2到10秒以上,然后继续执行,然后不久再次在监视器上等待。这些调用非常基本(例如System.getProperties),无法避免。JBoss和oth