Play Framework:数据库连接池关闭

问题描述:

我有一个使用HikariCP jdbc连接池运行的Play应用程序。Play Framework:数据库连接池关闭

该应用程序将运行良好一段时间,但经过一段时间后,它将关闭连接池,这意味着我不能再使用该应用程序。

SBT编译:

name := "virtual-betting" 
version := "1.0" 

lazy val root = (project in file(".")).enablePlugins(PlayJava).settings(javacOptions ++= Seq("-source", "1.8", "-target", "1.8")) 

scalaVersion := "2.11.8" 

libraryDependencies ++= Seq(
    javaJdbc, 
    javaJpa, 
    javaJpa.exclude("org.hibernate.javax.persistence", "hibernate-jpa-2.1-api"), 
    "org.hibernate" % "hibernate-core" % "5.1.0.Final", 
    "org.hibernate" % "hibernate-entitymanager" % "5.1.0.Final", 
    "com.typesafe.play" % "play-java-jpa_2.11" % "2.5.3", 
    "org.springframework" % "spring-context" % "4.2.4.RELEASE", 
    "org.webjars" % "bootstrap" % "3.3.4", 
    "mysql" % "mysql-connector-java" % "5.1.42", 
    cache, 
    javaWs, 
    "org.jsoup" % "jsoup" % "1.7.2", 
    "org.apache.commons" % "commons-email" % "1.4", 
    "org.apache.cxf" % "cxf-rt-rs-client" % "3.1.6", 
    "com.google.code.gson" % "gson" % "2.7", 
    "com.squareup.okhttp3" % "okhttp" % "3.4.1" 
) 

fork in run := false 


fork in run := true 

application.conf:

## Database Connection Pool 
# https://www.playframework.com/documentation/latest/SettingsJDBC 
# ~~~~~ 
# Play doesn't require a JDBC database to run, but you can easily enable one. 
# 
# libraryDependencies += jdbc 
# 

play.db { 
    # The combination of these two settings results in "db.default" as the 
    # default JDBC pool: 
    config = "db" 
    default = "default" 

    pool = "hikaricp" 
    # Play uses HikariCP as the default connection pool. You can override 
    # settings by changing the prototype: 

    prototype { 
    pool = "hikaricp" 

    # Sets a fixed JDBC connection pool size of 50 
    hikaricp.minimumIdle = 0 
    hikaricp.maximumPoolSize = 30 
    hikaricp.connectionTimeout = 30000 
    hikaricp.idleTimeout = 600000 
    hikaricp.maxLifetime = 1800000 
    hikaricp.leakDetectionThreshold = 5000 
    hikaricp.connectionTestQuery = "SELECT 1" 
    hikaricp.readOnly = false 

    hikari.dataSourceClassName = com.mysql.jdbc.jdbc2.optional.MysqlDataSource 
    # The database url 
    #url = "jdbc:mysql://localhost:3306/madduxsp_sportsbook?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8" 

    registerMBeans = true 
    poolName = "sportsbook_pool" 
    } 
} 

db.default.driver=com.mysql.jdbc.Driver 
db.default.url="jdbc:mysql://localhost:3306/madduxsp_sportsbook_new?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8" 
db.default.username=root 
db.default.password=mypassword 
db.default.jndiName=DefaultDS 
jpa.default=defaultPersistenceUnit 

application.secret="mysecret" 

spring.context.location=application-context.xml 

我已经写了一些代码,以保持数据库连接活着,这样的作品,如果它被关闭,由于闲置。

我DbKeepAliveService:

package services; 

import play.Logger; 
import play.db.jpa.JPAApi; 
import util.DbKeepAliveTask; 

import javax.inject.Inject; 
import javax.inject.Singleton; 
import java.util.Timer; 

@Singleton 
public class DbKeepAliveService { 

    private final JPAApi jpa; 

    @Inject 
    public DbKeepAliveService(JPAApi jpa) { 
     this.jpa = jpa; 

     DbKeepAliveTask dbKeepAliveTask = new DbKeepAliveTask(jpa); 
     Logger.info("Application has started"); 

     Timer timer = new Timer("dbKeepAlive", true); 
     timer.schedule(dbKeepAliveTask, 0, 1200000); 
    } 
} 

除了这不起作用。这里是我的日志:

2017-05-06 06:12:15,010 [INFO] from application in dbKeepAlive - Keeping database connection alive... 
2017-05-06 06:32:15,010 [INFO] from application in dbKeepAlive - Keeping database connection alive... 
2017-05-06 06:52:15,010 [INFO] from application in dbKeepAlive - Keeping database connection alive... 
2017-05-06 06:58:35,894 [INFO] from application in Thread-8 - Application shutdown... 
2017-05-06 06:58:36,054 [INFO] from application in Thread-8 - Shutting down connection pool. 

有没有人有任何想法,为什么它可能会继续关闭Db连接池?我怀疑这是与我的配置有关,但我真的不能确定。

我也读过它可能与未在生产模式下运行应用程序,但我已经设定了秘密。

我运行使用以下命令应用程序:

./bin/virtual-betting -Dconfig.file=conf/production.conf -Dplay.crypto.secret="mysecret" & 

随着在conf/production.conf文件play.crypto.secret属性集。

一直看着这个很长的时间,所以帮助是主要赞赏!

所以我发现了一段时间后我的问题是什么。这真的很愚蠢。

我没有用nohup命令启动我的应用程序。结果,该应用程序被操作系统用SIGTERM消息终止。

这是无关的我的应用程序在所有...

所以基本上,nohup的与管道出了输出到dev>空

生活和学习。

您可能想要删除minimumIdle配置建议由HikariCP

hikaricp.minimumIdle = 0 

HikariCP reference

也设置为默认做检查的30连接池大小是否足够好。

+0

谢谢@jayant这是一个非常令人沮丧的过程,至今我不得不说。我会看看两个 - 谢谢! –

+0

不幸的@jayant这似乎不是问题。今天早上我来看它,它又失败了。 –

查看您提供的日志,指出数据库连接池关闭的原因是因为应用程序(play)已关闭。

正如Play documentation说:

当您运行启动命令,播放叉一个新的JVM,并运行默认Netty的HTTP服务器。标准输出流被重定向到Play控制台,因此您可以监控其状态。

服务器的进程ID在引导时显示并写入RUNNING_PID文件。要杀死正在运行的Play服务器,向进程发送SIGTERM以正确关闭应用程序就足够了。

如果您键入Ctrl + D,Play控制台将退出,但创建的服务器进程将继续在后台运行。然后关闭分叉的JVM的标准输出流,并且可以从logs/application.log文件中读取日志记录。

因此,可能要么进程收到SIGTERM信号,播放应用程序启动与play run代替play start,有人用按Ctrl + d在控制台上或者是服务器杀死,因为它的进程是在存储器低运行其可以或可以不指示在应用程序内存泄漏看到OOM killer

在拼命低存储器的条件下,失存储器(OOM)杀手踢和挑选一个过程杀使用一系列随时间发展而来的启发式方法。

我建议你分析你的应用程序/监视服务器的内存(你也可以检查服务器日志,看看内核是否杀死了任何进程)。

如果您能够扩展HikariCPModule并覆盖close方法,您可以添加一个记录器调用来打印当前线程堆栈跟踪并验证实际调用关闭的内容,例如。关机挂钩或其他东西。

override def close(dataSource: DataSource) = { 
    Logger.info("Shutting down connection pool.") 
    Thread.dumpStack() 
    dataSource match { 
     case ds: HikariDataSource => ds.close() 
     case _ => sys.error("Unable to close data source: not a HikariDataSource") 
    } 

启用调试日志记录“com.zaxxer.hikari”和播放可帮助进一步诊断有什么不对数据库设置/应用程序。

祝你好运!