Play Framework:“连接太多”数据库错误

时间:2018-02-22 22:33:52

标签: postgresql scala playframework jooq

Play Framework 2.6,Postgresql。 Jooq作为db访问库。

运行测试时,我正在

  

org.postgresql.util.PSQLException:致命:抱歉,客户太多了   已经

这是一个提供jooq的dsl上下文的辅助类:

@Singleton
class Db @Inject() (val db: Database, system: ActorSystem) {

  val databaseContext: ExecutionContext = system.dispatchers.lookup("contexts.database")

  def query[A](block: DSLContext => A): Future[A] = Future {
    db.withConnection { connection: Connection =>
      val dsl = DSL.using(connection, SQLDialect.POSTGRES_9_4)
      block(dsl)
    }
  }(databaseContext)

  def withTransaction[A](block: DSLContext => A): Future[A] = Future {
    db.withTransaction { connection: Connection =>
      val dsl: DSLContext = DSL.using(connection, SQLDialect.POSTGRES_9_4)
      block(dsl)
    }
  }(databaseContext)
}

我在这样的存储库中使用这个助手类:

db.query { dsl =>
      val records = dsl
        .selectFrom(USERS)
        .where(...)
        ...  
      }
    }

application.conf

db.default.driver="org.postgresql.Driver"
db.default.url="jdbc:postgresql://localhost/postgres?user=postgres"

    ...
contexts { 
    database {
        executor = "thread-pool-executor"
        throughput = 1
        thread-pool-executor {
          fixed-pool-size = 9
        }
    }
}
...

build.sbt

...
libraryDependencies += jdbc
libraryDependencies += "org.jooq" % "jooq" % "3.10.5"
libraryDependencies += "org.jooq" % "jooq-codegen-maven" % "3.10.5"
libraryDependencies += "org.jooq" % "jooq-meta" % "3.10.5"
libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"
...

我所有测试的基本特征:

class BaseFeatureSpec extends FeatureSpec
  with GivenWhenThen
  with GuiceOneServerPerSuite
  with Matchers
  with WsScalaTestClient
  with BeforeAndAfterEach
  with MockitoSugar {

  override def fakeApplication(): Application =
    new GuiceApplicationBuilder()
      .overrides(bind[EmailService].to(classOf[EmailServiceStub]))
      .build()

  def config: Configuration = fakeApplication().configuration
  def actorSystem: ActorSystem = fakeApplication().actorSystem

  val db: Db = app.injector.instanceOf[Db]

  val wsClient: WSClient = app.injector.instanceOf[WSClient]
  val myPublicAddress = s"localhost:$port"

  private val injector = fakeApplication().injector

  def truncateDbOnEachRun = true

  override protected def beforeEach(): Unit = {
    if (truncateDbOnEachRun) {
      truncateDb
    }
  }

   protected def truncateDb = {
    await(db.withTransaction { dsl =>
      ... truncate all dbs...
    })
  }
}

我的postgresql实例的max_connections是100。

我注意到,在运行测试时,我发现在每次测试之前几次创建了池:

[info] application - Creating Pool for datasource 'default'
[info] application - Creating Pool for datasource 'default'
[info] application - Creating Pool for datasource 'default'
[info] application - Creating Pool for datasource 'default'

我收到too many connections错误后。

请帮忙。

2 个答案:

答案 0 :(得分:0)

看起来您使用默认类型的调度程序,尝试添加type = PinnedDispatcher,用于io类型调度程序,如下所示。

$(PackageOutputAbsolutePath)$(PackageId).$(PackageVersion).nupkg

你可以从中找到细节 https://doc.akka.io/docs/akka/2.5/dispatchers.html

答案 1 :(得分:0)

我发现了这个问题:

override def fakeApplication(): Application =
    new GuiceApplicationBuilder()
      .overrides(bind[EmailService].to(classOf[EmailServiceStub]))
      .build()

每次访问app.injector.instanceOf[Db]时都会创建新的应用程序实例(因为它是方法),这就是为什么我有这么多application - Creating Pool for datasource 'default'个日志的原因。

我已将def替换为val

override val fakeApplication(): Application =
        new GuiceApplicationBuilder()
          .overrides(bind[EmailService].to(classOf[EmailServiceStub]))
          .build()

它运作正常。