我们在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)
....
几个问题。
以防这是我们在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 - 是否有任何DBCP配置可以修复阻塞?
虽然我在文档中看不到它,但我认为资源节点中还应该有一个名为'WhenExaustedAction'的设置属性,它可以取值“GROW”(值2)而不是“BLOCK”(值1)或“失败“(值0)。这直接来自Pools常见。 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
和至少connectionCacheName
和connectionCacheProperties
。通过这种方式,我会引诱DBCP相信它正在做真正的工作并实际使用Oracle的池化机制。这也意味着DBCP承担的风险很小,从而对maxActive设置进行更自由的调整。