我们在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 配置可以修复阻塞?
- OpenEJB 中的 DBCP 连接池实现可以替换吗?用另一个库替换它有多容易(困难)?
以防万一,这就是我们在 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>
最佳答案
我的 2 克拉...
1 - Are there any DBCP configurations that may fix blocking?
虽然我在文档中看不到它,但我认为资源节点中还应该有一个名为“WhenExaustedAction”的设置属性,该属性可以采用值“GROW”(值 2)而不是“BLOCK”(值 1) )或“失败”(值 0)。这直接来自公共(public)池。 Hibernate 和 Cayenne 都使用此 DBCP 设置。不过不了解 OpenEJB。
不用说,这只有在所有连接都尽职尽责地关闭的情况下才有效(有时很难保证)。 然后,您可能可以通过 JMX 查看在高峰 Activity 时间需要多少连接,然后您可以将 maxActive 设置为根据这些措施得出的更高值。
2 - Is DBCP connection pool implementation replaceable in OpenEJB? How easy (difficult) to replace it with another library?
抱歉不知道。可以想象是的。或者 DBCP 可能允许另一个连接池管理器。
更新:刚刚查看了代码,似乎 DBCP 是连接池的唯一选项。
顺便说一句,我看到了whenExhaustedAction 设置。 openejb.xml 不支持。
不过,由于您使用的是 Oracle 数据库,因此仍然剩下一个选项。
您可以尝试的一件事是使用 Oracle 隐式连接缓存(假设版本 10g)并为 DBCP 留下任意“足够”数量的连接。
为此,您需要在 openejb.xml 资源 block 中配置 ConnectionProperties
属性并使用 Oracle JDBC 连接属性。即 connectionCachingEnabled=true
以及至少 connectionCacheName
和 connectionCacheProperties
。通过这种方式,我会诱使 DBCP 相信它正在做真正的工作并且实际上使用了 Oracle 的池机制。这也意味着 DBCP 的风险很小,从而可以更自由地调整 maxActive 设置的大小。
关于java - 阻塞 DBCP 连接池(打开和关闭连接)。 OpenEJB 中的数据库连接池是可插拔的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4853732/