我们在 Tomcat 上使用 OpenEJB(用于在 JBoss、Weblogic 等上运行)。在运行负载测试时,我们在处理 JMS 消息(队列)时遇到了严重的性能问题。问题已本地化为阻止数据库连接池获取或释放与池的连接。阻塞阻止并发 MDB 实例(线程)运行,因此性能下降了 10 倍甚至更糟。用于在应用程序服务器(及其各自的连接池实现)上运行的相同代码完全没有阻塞。
线程阻塞示例:
Name: JMS Resource Adapter-worker-23
State: BLOCKED on org.apache.commons.pool.impl.GenericObjectPool@1ea6b4a owned by: JMS Resource Adapter-worker-19
Total blocked: 18,426 Total waited: 0
Stack trace:
org.apache.commons.pool.impl.GenericObjectPool.returnObject(GenericObjectPool.java:916)
org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:91)
- locked org.apache.commons.dbcp.PoolableConnection@1bcba8
org.apache.commons.dbcp.managed.ManagedConnection.close(ManagedConnection.java:147)
com.xxxxx.persistence.DbHelper.closeConnection(DbHelper.java:290)
....
几个问题。
- 我几乎可以肯定,一些事务性属性和属性会导致这种阻塞,但是 MDB 被定义为非事务性的(我们同时使用注释和 ejb-jar.xml)。不过,一些 EJB 确实使用容器管理的事务(我们也可以观察到那里的阻塞)。是否有任何可以修复阻塞的 DBCP 配置?
- DBCP 连接池实现在 OpenEJB 中是否可替换?用另一个库替换它有多容易(困难)?
以防这是我们在 OpenEJB (openejb.xml) 中定义数据源的方式:
<Resource id="MyDataSource" type="DataSource">
JdbcDriver oracle.jdbc.driver.OracleDriver
JdbcUrl ${oracle.jdbc}
UserName ${oracle.user}
Password ${oracle.password}
JtaManaged true
InitialSize 5
MaxActive 30
ValidationQuery SELECT 1 FROM DUAL
TestOnBorrow true
</Resource>