我发现JPA有些奇怪的行为。在某些情况下,我们收到了错误
"Timed out waiting for a free available connection."
at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:88) ~[bonecp.jar:na]
我做了简单的研究,发现了这个:
对于进程@Transaction请求,Play2至少使用2个不同的actor:
从游泳池获取连接并处理呼叫的一个角色。
相关代码:
提交或回滚事务的第二个actor。此时发布连接。
相关代码:
两个actor都是从一个akka执行器和线程池执行的。看:http://www.playframework.com/documentation/2.2.x/ThreadPools
默认情况下有24个帖子。
假设我们有一个必须处理许多并发请求的高负载应用程序。在我的测试中,我遇到了50多个并发默认配置请求的问题。 您可以重复我的测试并仅使用非默认配置的3个并发请求来捕获此问题,如下所示:
play {
akka {
akka.loggers = ["akka.event.Logging$DefaultLogger", "akka.event.slf4j.Slf4jLogger"]
loglevel = DEBUG
actor {
default-dispatcher = {
fork-join-executor {
parallelism-factor = 1.0
parallelism-min = 1
parallelism-max = 1
}
}
}
}
}
...
db.default.minConnectionsPerPartition=2
db.default.maxConnectionsPerPartition=2
...
复杂性和处理时间对于此测试无关紧要。我的处理时间是7毫秒(解析参数+一个插入到数据库)。您只需要发送比连接池大小更多的并发请求。 现在我写下我认为正在发生的事情。
许多演员试图从游泳池获得连接。但目前没有可用的免费连接(所有其他演员捕获它们)。此连接池基于BlockingQueue。码: https://github.com/wwadge/bonecp/blob/master/bonecp/src/main/java/com/jolbox/bonecp/DefaultConnectionStrategy.java#L82
因此当前线程在此行被阻止超时(默认为一秒)。
看起来像死锁。
有人可以给我一个建议,我该如何避免这个问题?
答案 0 :(得分:0)
有人可以给我一个建议,我该如何避免这个问题?
避免使用Akka actor直接向同一资源发出多个同时发生的潜在阻塞请求。使用单独的线程池来代替JDBC。
答案 1 :(得分:0)
实际上你的代码没有通过这里的演员,但它是在不同的线程之间传递。
您应该将线程池配置为较大,正如在本文档中阻止Java应用程序所做的那样:
http://www.playframework.com/documentation/2.2.x/ThreadPools