0

我们在 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)
....

几个问题。

  1. 我几乎可以肯定,一些事务性属性和属性会导致这种阻塞,但是 MDB 被定义为非事务性的(我们同时使用注释和 ejb-jar.xml)。不过,一些 EJB 确实使用容器管理的事务(我们也可以观察到那里的阻塞)。是否有任何可以修复阻塞的 DBCP 配置?
  2. 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>
4

2 回答 2

1

我的 2 克拉...

1 - 是否有任何可以修复阻塞的 DBCP 配置?

虽然我在文档中看不到它,但我认为资源节点中还应该有一个名为“WhenExaustedAction”的设置属性,它可以取值“GROW”(值 2)而不是“BLOCK”(值 1)或“失败”(值 0)。这直接来自常见的池。Hibernate 和 Cayenne 都使用此 DBCP 设置。虽然不知道 OpenEJB。

无需说这只有在所有连接都尽职尽责的情况下才有效(这有时很难保证)。然后,您可能可以通过 JMX 看到在活动高峰期需要多少连接,然后您可以将 maxActive 设置为从这些措施演变而来的更高值。

2 - 在 OpenEJB 中 DBCP 连接池实现是否可替换?用另一个库替换它有多容易(困难)?

抱歉不知道。可以想象是的。或者可能 DBCP 允许另一个连接池管理器。

更新:刚刚查看了代码,似乎 DBCP 是连接池的唯一选择。

顺便说一句,我已经看到了 whenExhaustedAction 设置。openejb.xml 不支持。
但是,由于您使用的是 Oracle 数据库,因此仍然存在一个选项。
您可以尝试的一件事是使用 Oracle 隐式连接缓存(假设版本 10g)并为 DBCP 保留任意“足够”数量的连接。为此,您需要在 openejb.xml 资源块中配置ConnectionProperties属性并使用 Oracle JDBC 连接属性。那是connectionCachingEnabled=true和 至少connectionCacheNameconnectionCacheProperties。通过这种方式,我会诱使 DBCP 相信它在做真正的工作,并且实际上使用了 Oracle 的池化机制。这也意味着使用 DBCP 承担的风险很小,因此 maxActive 设置的大小更加自由。

于 2011-02-02T21:01:15.817 回答
1

通过更改池配置 ( openejb.xml )解决了 dbcp 阻塞问题:

TestOnBorrow false

谢谢你,Andy,来自 OpenEJB 团队!

于 2011-02-18T16:59:18.990 回答