Slick和bonecp:org.postgresql.util.PSQLException:致命:对不起,太多的客户已经报错 [英] Slick and bonecp: org.postgresql.util.PSQLException: FATAL: sorry, too many clients already error
问题描述
在本地开发应用程序时,我使用sbt run
Locally when I am developing my application I launch my play2 application using sbt run
我喜欢更改代码,然后重新加载浏览器以查看更改的方法.
I love how I can make code changes, and then reload my browser to see my changes.
大约10次代码更改后,我收到一个postgresql太多的连接错误(见下文).
After about roughly 10 code changes or so, I get a postgresql too many connection error (see below).
我的数据库连接使用下面的DatabaseAccess.scala类.
My db connection is using the below DatabaseAccess.scala class.
我猜每次重载都会创建到Postgresql的连接.在我目前正在做的Global工作中:
I'm guessing on each reload it is creating a bunch of connections to postgresql. In my Global am currently doing:
override def onStart(app: Application) {
Logger.info("Global.onStart")
DatabaseAccess.loadConfiguration()
}
在生产环境中,我还担心,如果我在短时间内进行多次部署,或者启动/停止我的服务,我也会遇到这个问题.
In production I am also worried that if I make multiple deploys in a short period of time, or start/stop my service I might run into this problem also.
如何确保所有连接都被销毁?我知道我可以在onStart或OnStop中放置一些内容,但我不确定如何清除以前可能存在的连接. (假设这不是错误)
我确实创建了一个我在onStop上调用的release()方法,但似乎没有用:
I did create a release() method that I was calling on onStop but that didn't seem to work:
def release() {
configs = Map[String, BoneCPConfig]()
dataSources = Map[String, BoneCPDataSource]()
databases = dataSources.map { case(key, value) => (key, Database.forDataSource(value)) }
}
我所做的就是重新初始化var,所以我猜那并不是我真正需要做的.
All I did was re-init the vars so I guess that wasn't really what I needed to do.
我的数据访问模式如下:
def getById(userId: Int): Option[User] = {
db.withSession { implicit session =>
return userDao.getById(userId)
}
}
我的数据库访问类如下:
My database access class looks like:
我的application.conf连接如下:
My application.conf connection looks like:
#postgresql
db.default.driver="org.postgresql.Driver"
db.default.url = "jdbc:postgresql://localhost/testweb_development"
db.default.user = "testdbuser"
db.default.password = ""
db.default.minConnections = 4
db.default.maxConnections = 24
db.default.maxThreads = 2
在大约10次代码更改和sbt之后进行本地开发时,很好的局部类重载时出现此错误:
Locally when developing after about approximately 10 code changes and sbt doing it's nice partial class reloads I get this error:
play.api.Application$$anon$1: Execution exception[[SQLException: Unable to open a test connection to the given database. JDBC url = jdbc:postgresql://localhost/testweb_development, username = testdbuser. Terminating connection pool (set lazyInit to true if you expect to start your database after your app). Original Exception: ------
org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:291)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:108)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:125)
at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)
at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:22)
at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:30)
at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24)
at org.postgresql.Driver.makeConnection(Driver.java:393)
at org.postgresql.Driver.connect(Driver.java:267)
at java.sql.DriverManager.getConnection(DriverManager.java:582)
at java.sql.DriverManager.getConnection(DriverManager.java:185)
at com.jolbox.bonecp.BoneCP.obtainRawInternalConnection(BoneCP.java:363)
at com.jolbox.bonecp.BoneCP.<init>(BoneCP.java:416)
at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:120)
at scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon$4.createConnection(JdbcBackend.scala:47)
at scala.slick.jdbc.JdbcBackend$BaseSession.conn$lzycompute(JdbcBackend.scala:302)
at scala.slick.jdbc.JdbcBackend$BaseSession.conn(JdbcBackend.scala:302)
at scala.slick.jdbc.JdbcBackend$BaseSession.close(JdbcBackend.scala:316)
at scala.slick.backend.DatabaseComponent$DatabaseDef$class.withSession(DatabaseComponent.scala:31)
at scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon$4.withSession(JdbcBackend.scala:46)
at com.exampleapp.services.UserServiceImpl.getById(UserService.scala:37)
at controllers.UsersController$$anonfun$show$1.apply(UsersController.scala:84)
at controllers.UsersController$$anonfun$show$1.apply(UsersController.scala:76)
at play.api.mvc.ActionBuilder$$anonfun$apply$10.apply(Action.scala:221)
at play.api.mvc.ActionBuilder$$anonfun$apply$10.apply(Action.scala:220)
at controllers.ActionWithContext$.invokeBlock(BaseController.scala:42)
at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:309)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:109)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:109)
at play.utils.Threads$.withContextClassLoader(Threads.scala:18)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:108)
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:107)
at scala.Option.map(Option.scala:145)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:107)
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:100)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:481)
at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:481)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:517)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:517)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:493)
at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:493)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:42)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
环境
I am running scala 2.10.3, play 2.2.3
I am launching my app using sbt run.
Postgresql driver version: 9.1-901.jdbc4
slick version: 2.0.1
bonecp version: 0.8.0.RELEASE
推荐答案
Slick
自动处理会话关闭.从文档中:
Slick
handles session closing automatically. From the documentation:
Database对象的withSession方法创建一个Session,将其传递给给定的函数,然后将其关闭.如果您使用连接池,则关闭会话将把连接返回到该池.
The Database object’s withSession method creates a Session, passes it to a given function and closes it afterwards. If you use a connection pool, closing the Session returns the connection to the pool.
问题是Bonecp
的dataSource
连接没有关闭,如这所示要点,您需要使用dataSource.close()
手动将其关闭.
The problem is the Bonecp
's dataSource
connections which are not closed, as showed on this gist you need to close them manually using dataSource.close()
.
这篇关于Slick和bonecp:org.postgresql.util.PSQLException:致命:对不起,太多的客户已经报错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!