java - 阻塞 DBCP 连接池(打开和关闭连接)。 OpenEJB 中的数据库连接池是可插拔的吗?

标签 java transactions connection-pooling blocking openejb

我们在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. 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 以及至少 connectionCacheNameconnectionCacheProperties。通过这种方式,我会诱使 DBCP 相信它正在做真正的工作并且实际上使用了 Oracle 的池机制。这也意味着 DBCP 的风险很小,从而可以更自由地调整 maxActive 设置的大小。

关于java - 阻塞 DBCP 连接池(打开和关闭连接)。 OpenEJB 中的数据库连接池是可插拔的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4853732/

相关文章:

Java 删除一个迭代器,该迭代器删除同一列表中的另一个元素

Cooja 模拟器中的 Java 结果 134

python - 用 Python 为非数据库代码编写事务

python - 在 Redis Python 中创建和管理多个连接

java - 如何处理maven下载的api中缺少的ExpressionFactory#newInstance()方法?

java - 如何使用限制在 hibernate 标准中获取月/日与另一个没有年份的月/日进行比较

node.js - 在 forEach 问题中对交易进行 Sequelize

python - 确保外部 API 结果的连接和响应的最佳实践

SQL 池与 Entity Framework

mysql - Nodejs Mysql 库错误 "Too many connections"