当一个连接池无法初始化时,所有连接池都无法初始化

时间:2017-11-12 08:55:02

标签: scala jdbc playframework

这是一个错误吗?

我正在使用Play框架2.6.6和scala 2.12.3。我在application.conf中定义了3个数据库(hikaricp连接池的设置遍布地图,因为我尝试了它们):

db {
  mentions {
    driver="org.postgresql.Driver"
    url="jdbc:postgresql://localhost:5432/mentions"
    password="***"
    username="play"
    hikaricp {
      maximumPoolSize = 2
      minimumIdle=2
    }

  }

  postgres {
    driver="org.postgresql.Driver"
    url="jdbc:postgresql://localhost:5432/postgres"
    password="***"
    username="postgres"
    hikaricp {
      maximumPoolSize = 9
      minimumIdle=9
    }
  }

  sqlserver {
    driver="net.sourceforge.jtds.jdbc.Driver"
    url="jdbc:jtds:sqlserver://10.211.55.5:1433/db"
    username="sa"
    password="***"
    hikaricp {
      maximumPoolSize=4
      minimumIdle=4
      //connectionTestQuery="select 1"
    }
  }

}

使用此配置,Hikaricp连接池无法初始化sql server连接池,实际上没有其他两个连接池被初始化。修复sql server连接错误的方法是设置connectionTestQuery。这不是这篇文章的重点。我不明白为什么其他两个连接失败时会失败。在我看来,其他两个连接池仍应运行。

以下是来自控制台的错误消息:

[info] application - Creating Pool for datasource 'sqlserver'
[error] c.z.h.p.PoolBase - HikariPool-1 - Failed to execute isValid() for connection, configure connection test query (null).
[info] application - Creating Pool for datasource 'sqlserver'
[error] c.z.h.p.PoolBase - HikariPool-2 - Failed to execute isValid() for connection, configure connection test query (null).
[info] application - Creating Pool for datasource 'sqlserver'
[error] c.z.h.p.PoolBase - HikariPool-3 - Failed to execute isValid() for connection, configure connection test query (null).
[error] application - 

! @761fipg95 - Internal server error, for (GET) [/] ->

play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) Error injecting method, java.lang.AbstractMethodError
  at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
  at play.api.db.DBModule$$anonfun$$lessinit$greater$1.$anonfun$new$1(DBModule.scala:25):
Binding(interface play.api.db.Database qualified with QualifierInstance(@play.db.NamedDatabase(value=sqlserver)) to ProviderTarget(play.api.db.NamedDatabaseProvider@65c05a8b)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

2) Error injecting method, java.lang.AbstractMethodError
  at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
  at play.api.db.DBModule$$anonfun$$lessinit$greater$1.$anonfun$new$1(DBModule.scala:25):
Binding(interface play.api.db.Database qualified with QualifierInstance(@play.db.NamedDatabase(value=mentions)) to ProviderTarget(play.api.db.NamedDatabaseProvider@700c1d35)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

3) Error injecting method, java.lang.AbstractMethodError
  at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
  at play.api.db.DBModule$$anonfun$$lessinit$greater$1.$anonfun$new$1(DBModule.scala:25):
Binding(interface play.api.db.Database qualified with QualifierInstance(@play.db.NamedDatabase(value=postgres)) to ProviderTarget(play.api.db.NamedDatabaseProvider@1f4f0047)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

3 errors]
    at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:186)
    at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:124)
    at play.core.server.AkkaHttpServer.modelConversion(AkkaHttpServer.scala:183)
    at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:189)
    at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$3(AkkaHttpServer.scala:106)
    at akka.stream.impl.fusing.MapAsync$$anon$23.onPush(Ops.scala:1172)
    at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:499)
    at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:462)
    at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:368)
    at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:571)
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting method, java.lang.AbstractMethodError
  at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
  at play.api.db.DBModule$$anonfun$$lessinit$greater$1.$anonfun$new$1(DBModule.scala:25):
Binding(interface play.api.db.Database qualified with QualifierInstance(@play.db.NamedDatabase(value=sqlserver)) to ProviderTarget(play.api.db.NamedDatabaseProvider@65c05a8b)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

2) Error injecting method, java.lang.AbstractMethodError
  at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
  at play.api.db.DBModule$$anonfun$$lessinit$greater$1.$anonfun$new$1(DBModule.scala:25):
Binding(interface play.api.db.Database qualified with QualifierInstance(@play.db.NamedDatabase(value=mentions)) to ProviderTarget(play.api.db.NamedDatabaseProvider@700c1d35)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

3) Error injecting method, java.lang.AbstractMethodError
  at com.google.inject.util.Providers$GuicifiedProviderWithDependencies.initialize(Providers.java:149)
  at play.api.db.DBModule$$anonfun$$lessinit$greater$1.$anonfun$new$1(DBModule.scala:25):
Binding(interface play.api.db.Database qualified with QualifierInstance(@play.db.NamedDatabase(value=postgres)) to ProviderTarget(play.api.db.NamedDatabaseProvider@1f4f0047)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

3 errors
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
    at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:176)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
    at com.google.inject.Guice.createInjector(Guice.java:99)
    at com.google.inject.Guice.createInjector(Guice.java:84)
    at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:185)
    at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
    at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
    at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:174)
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
Caused by: java.lang.AbstractMethodError: null
    at net.sourceforge.jtds.jdbc.JtdsConnection.isValid(JtdsConnection.java:2833)
    at com.zaxxer.hikari.pool.PoolBase.checkDriverSupport(PoolBase.java:456)
    at com.zaxxer.hikari.pool.PoolBase.setupConnection(PoolBase.java:423)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:381)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:205)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:448)
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:519)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:113)
    at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:72)
    at play.api.db.HikariCPConnectionPool.$anonfun$create$1(HikariCPModule.scala:51)

更新:我仍然认为在架构上,如果一个连接池不起作用,其他连接池不应受到影响。今天我关闭运行sql server的windows vm,我只运行了postgresql服务器。我测试的页面只连接到postgresql dbs,它仍然失败,因为sql server连接池没有工作。这次失败了,配置错误java.sql.SQLException - Login Timed out。

1 个答案:

答案 0 :(得分:0)

在2.6.6&amp;进行一些调试后2.6.7,我发现了以下内容:

java.lang.AbstractMethodError继承继承java.lang.LinkageError的java.lang.IncompatibleClassChangeError。根据NonFatal对象,java.lang.LinkageError被视为致命错误:

object NonFatal {
   /**
    * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal
    */
   def apply(t: Throwable): Boolean = t match {
     // VirtualMachineError includes OutOfMemoryError and other fatal errors
     case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
     case _ => true
   }
  /**
   * Returns Some(t) if NonFatal(t) == true, otherwise None
   */
  def unapply(t: Throwable): Option[Throwable] = if (apply(t)) Some(t) else None
}

因此,遍布代码的Try调用不会捕获此异常。

异常最终由guice图层处理。该调用返回到guice Initializer.injectAll方法,该方法(以及其他对象)为application.conf文件中配置的每个数据库连接注入NamedDatabaseProvider对象(与DBModule连接到NamedDatabaseProvider的绑定)。 NamedDatabaseProvider对象依赖于DBApi,由于AbstractMethodError异常被认为是致命的,因此每次初始化都会失败。

最终问题是情况的组合:1。Hikaricp代码中的异常抛出是致命的,2。DBApi代码想要初始化所有连接池并且它不会处理致命错误。

我不认为这是一个错误。也许Hickaricp家伙可能会抛出UnsupportedOperationException或similar

对于其他感兴趣的人,我发现了这个:https://github.com/njlg/playdb