2017-05-06 151 views
0

我有一個使用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屬性集。

一直看着這個很長的時間,所以幫助是主要讚賞!

回答

0

所以我發現了一段時間後我的問題是什麼。這真的很愚蠢。

我沒有用nohup命令啓動我的應用程序。結果,該應用程序被操作系統用SIGTERM消息終止。

這是無關的我的應用程序在所有...

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

生活和學習。

0

您可能想要刪除minimumIdle配置建議由HikariCP

hikaricp.minimumIdle = 0 

HikariCP reference

也設置爲默認做檢查的30連接池大小是否足夠好。

+0

謝謝@jayant這是一個非常令人沮喪的過程,至今我不得不說。我會看看兩個 - 謝謝! –

+0

不幸的@jayant這似乎不是問題。今天早上我來看它,它又失敗了。 –

2

查看您提供的日誌,指出數據庫連接池關閉的原因是因爲應用程序(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」和播放可幫助進一步診斷有什麼不對數據庫設置/應用程序。

祝你好運!