Apache Pool 2 库 - 连接不会自动关闭
Apache Pool 2 library - connections not closed automatically
我在使用 Apache pool2
库的 Scala 中有以下代码。要池化的对象是 OlapConnection
(olap4j
class,类似于 SQL 连接)。
问题是当池中对象的数量超过最大值时,我无法让池自动关闭连接。
如果我 return 一个对象到触发 passivateObject
的池(pool.returnObject
)。如果我在 passivateObject
中关闭连接,我会在每次 return 对象时关闭它,这不是我想要的 - 我需要缓存打开的连接。如果我不关闭passivateObject
中的连接,那么它将永远不会关闭。
如何进行这项工作?
Scala 代码:
class OlapConnectionUtil (val pool: ObjectPool[OlapConnection]) {
def connect = {
pool.borrowObject
}
def close(olapConnection: OlapConnection) = {
pool.returnObject(olapConnection)
}
}
class OlapConnectionFactory extends BasePooledObjectFactory[OlapConnection] {
override def create = {
val connectionString = "jdbc:mondrian:Jdbc=jdbc:mysql://localhost:3306/foodmart?" +
"user=x&password=x;Catalog=FoodMart.xml;JdbcDrivers=com.mysql.jdbc.Driver"
val connection = DriverManager.getConnection(connectionString)
connection.unwrap(classOf[OlapConnection])
}
override def wrap(olapConnection: OlapConnection) =
new DefaultPooledObject(olapConnection)
override def passivateObject(pooledObject: PooledObject[OlapConnection] ) {
println("passivateObject WAS CALLED")
pooledObject.getObject.close
}
}
class Test {
val olapConnectionFactory = new OlapConnectionFactory
def test = {
val config = new GenericObjectPoolConfig
config.setMaxIdle(5)
config.setMaxTotal(10)
val util = new OlapConnectionUtil(
new GenericObjectPool[OlapConnection](olapConnectionFactory,config))
val olapConnection = util.connect
// do stuff with olapConnection
util.close(olapConnection)
如果您打开 PooledObjectFactory
的 JavaDocs,您可能会看到
passivateObject(org.apache.commons.pool2.PooledObject<T>)
is invoked on every instance when it is returned to the pool.
destroyObject(org.apache.commons.pool2.PooledObject<T>)
is invoked on every instance when it is being "dropped" from the pool (whether due to the response from validateObject(org.apache.commons.pool2.PooledObject<T>)
, or for reasons specific to the pool implementation.) There is no guarantee that the instance being destroyed will be considered active, passive or in a generally consistent state.
换句话说,您应该将资源解除分配逻辑放入destroyObject
。这是你的一个修改后的测试,带有一个假 OlapConnection
实现
import org.apache.commons.pool2._
import org.apache.commons.pool2.impl._
// fake!
case class OlapConnection(val id: Int) {
def close(): Unit = {
println(s"Close was called for $this")
}
}
class OlapConnectionUtil(val pool: ObjectPool[OlapConnection]) {
def connect = {
pool.borrowObject
}
def close(olapConnection: OlapConnection) = {
pool.returnObject(olapConnection)
}
}
class OlapConnectionFactory extends BasePooledObjectFactory[OlapConnection] {
var cnt = 0
override def create = {
cnt += 1
new OlapConnection(cnt)
}
override def wrap(olapConnection: OlapConnection) =
new DefaultPooledObject(olapConnection)
override def passivateObject(pooledObject: PooledObject[OlapConnection]) {
println("-passivateObject was called")
}
override def destroyObject(pooledObject: PooledObject[OlapConnection]): Unit = {
super.destroyObject(pooledObject)
println("--destroyObject was called")
pooledObject.getObject.close
}
}
object Test {
val olapConnectionFactory = new OlapConnectionFactory
def test = {
val config = new GenericObjectPoolConfig
config.setMaxIdle(5)
config.setMaxTotal(10)
val util = new OlapConnectionUtil(new GenericObjectPool[OlapConnection](olapConnectionFactory, config))
val initConnections = (1 to 10).map(i => util.connect).toList
val closeCons = initConnections
Thread.sleep(100)
println("Start closing")
closeCons.zipWithIndex.foreach(ci => {
Thread.sleep(100)
println(s"Before close ${ci._2 + 1}")
util.close(ci._1)
println(s"After close ${ci._2 + 1}")
})
}
}
这段代码产生的输出是:
Before close 1
-passivateObject was called
After close 1
Before close 2
-passivateObject was called
After close 2
Before close 3
-passivateObject was called
After close 3
Before close 4
-passivateObject was called
After close 4
Before close 5
-passivateObject was called
After close 5
Before close 6
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(6)
After close 6
Before close 7
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(7)
After close 7
Before close 8
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(8)
After close 8
Before close 9
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(9)
After close 9
Before close 10
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(10)
After close 10
如您在此输出中所见,close
自 OlapConnection(6)
以来被调用,正如人们所期望的给定池配置。
我在使用 Apache pool2
库的 Scala 中有以下代码。要池化的对象是 OlapConnection
(olap4j
class,类似于 SQL 连接)。
问题是当池中对象的数量超过最大值时,我无法让池自动关闭连接。
如果我 return 一个对象到触发 passivateObject
的池(pool.returnObject
)。如果我在 passivateObject
中关闭连接,我会在每次 return 对象时关闭它,这不是我想要的 - 我需要缓存打开的连接。如果我不关闭passivateObject
中的连接,那么它将永远不会关闭。
如何进行这项工作?
Scala 代码:
class OlapConnectionUtil (val pool: ObjectPool[OlapConnection]) {
def connect = {
pool.borrowObject
}
def close(olapConnection: OlapConnection) = {
pool.returnObject(olapConnection)
}
}
class OlapConnectionFactory extends BasePooledObjectFactory[OlapConnection] {
override def create = {
val connectionString = "jdbc:mondrian:Jdbc=jdbc:mysql://localhost:3306/foodmart?" +
"user=x&password=x;Catalog=FoodMart.xml;JdbcDrivers=com.mysql.jdbc.Driver"
val connection = DriverManager.getConnection(connectionString)
connection.unwrap(classOf[OlapConnection])
}
override def wrap(olapConnection: OlapConnection) =
new DefaultPooledObject(olapConnection)
override def passivateObject(pooledObject: PooledObject[OlapConnection] ) {
println("passivateObject WAS CALLED")
pooledObject.getObject.close
}
}
class Test {
val olapConnectionFactory = new OlapConnectionFactory
def test = {
val config = new GenericObjectPoolConfig
config.setMaxIdle(5)
config.setMaxTotal(10)
val util = new OlapConnectionUtil(
new GenericObjectPool[OlapConnection](olapConnectionFactory,config))
val olapConnection = util.connect
// do stuff with olapConnection
util.close(olapConnection)
如果您打开 PooledObjectFactory
的 JavaDocs,您可能会看到
passivateObject(org.apache.commons.pool2.PooledObject<T>)
is invoked on every instance when it is returned to the pool.destroyObject(org.apache.commons.pool2.PooledObject<T>)
is invoked on every instance when it is being "dropped" from the pool (whether due to the response fromvalidateObject(org.apache.commons.pool2.PooledObject<T>)
, or for reasons specific to the pool implementation.) There is no guarantee that the instance being destroyed will be considered active, passive or in a generally consistent state.
换句话说,您应该将资源解除分配逻辑放入destroyObject
。这是你的一个修改后的测试,带有一个假 OlapConnection
实现
import org.apache.commons.pool2._
import org.apache.commons.pool2.impl._
// fake!
case class OlapConnection(val id: Int) {
def close(): Unit = {
println(s"Close was called for $this")
}
}
class OlapConnectionUtil(val pool: ObjectPool[OlapConnection]) {
def connect = {
pool.borrowObject
}
def close(olapConnection: OlapConnection) = {
pool.returnObject(olapConnection)
}
}
class OlapConnectionFactory extends BasePooledObjectFactory[OlapConnection] {
var cnt = 0
override def create = {
cnt += 1
new OlapConnection(cnt)
}
override def wrap(olapConnection: OlapConnection) =
new DefaultPooledObject(olapConnection)
override def passivateObject(pooledObject: PooledObject[OlapConnection]) {
println("-passivateObject was called")
}
override def destroyObject(pooledObject: PooledObject[OlapConnection]): Unit = {
super.destroyObject(pooledObject)
println("--destroyObject was called")
pooledObject.getObject.close
}
}
object Test {
val olapConnectionFactory = new OlapConnectionFactory
def test = {
val config = new GenericObjectPoolConfig
config.setMaxIdle(5)
config.setMaxTotal(10)
val util = new OlapConnectionUtil(new GenericObjectPool[OlapConnection](olapConnectionFactory, config))
val initConnections = (1 to 10).map(i => util.connect).toList
val closeCons = initConnections
Thread.sleep(100)
println("Start closing")
closeCons.zipWithIndex.foreach(ci => {
Thread.sleep(100)
println(s"Before close ${ci._2 + 1}")
util.close(ci._1)
println(s"After close ${ci._2 + 1}")
})
}
}
这段代码产生的输出是:
Before close 1
-passivateObject was called
After close 1
Before close 2
-passivateObject was called
After close 2
Before close 3
-passivateObject was called
After close 3
Before close 4
-passivateObject was called
After close 4
Before close 5
-passivateObject was called
After close 5
Before close 6
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(6)
After close 6
Before close 7
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(7)
After close 7
Before close 8
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(8)
After close 8
Before close 9
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(9)
After close 9
Before close 10
-passivateObject was called
--destroyObject was called
Close was called for OlapConnection(10)
After close 10
如您在此输出中所见,close
自 OlapConnection(6)
以来被调用,正如人们所期望的给定池配置。