启动没有 DB 的 Java/Play2.5 REST API

Posted

技术标签:

【中文标题】启动没有 DB 的 Java/Play2.5 REST API【英文标题】:Start Java/Play2.5 REST API without DB 【发布时间】:2017-05-15 12:17:36 【问题描述】:

我想开始我的 Java/Play!即使无法访问数据库也可以提供服务。到目前为止,如果数据库不可用,服务就会停止。是否可以在 Play 中尝试每隔一秒左右重新连接一次,而无需完全停止服务并在连接可用时立即重新连接到 db。

我们的 application.conf 目前看起来像这样:

play.evolutions.enabled=false
//play.db.pool=bonecp

db 
   default.driver=org.postgresql.Driver
   default.url="jdbc:postgresql://postgresdb.postgres:5432/postcode"
   default.username="<username>"
   default.password="<strong-password>"


play.db 
  config = "db"
  prototype.hikaricp = 
    connectionTimeout = 250 milliseconds
    initializationFailFast = false
    readOnly = true
  


ebean.default = ["models.*"]

目前我得到以下日志:

2017-05-15 13:26:54.525 [error] postcode-play: Connection error: 
org.postgresql.util.PSQLException: FATAL: remaining connection slots are reserved for non-replication superuser connections
  Ort: Datei: postinit.c, Routine: InitPostgres, Zeile: 779.
  Server SQLState: 53300
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
    at org.postgresql.core.v3.QueryExecutorImpl.readStartupMessages(QueryExecutorImpl.java:2538)
    at org.postgresql.core.v3.QueryExecutorImpl.<init>(QueryExecutorImpl.java:122)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:227)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:194)
    at org.postgresql.Driver.makeConnection(Driver.java:431)
    at org.postgresql.Driver.connect(Driver.java:247)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:101)

2017-05-15 13:26:54.626 [error] postcode-play: Connection error: 
org.postgresql.util.PSQLException: FATAL: remaining connection slots are reserved for non-replication superuser connections
  Ort: Datei: postinit.c, Routine: InitPostgres, Zeile: 779.
  Server SQLState: 53300
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
    at org.postgresql.core.v3.QueryExecutorImpl.readStartupMessages(QueryExecutorImpl.java:2538)
    at org.postgresql.core.v3.QueryExecutorImpl.<init>(QueryExecutorImpl.java:122)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:227)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:194)
    at org.postgresql.Driver.makeConnection(Driver.java:431)
    at org.postgresql.Driver.connect(Driver.java:247)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:101)
.
.
.

表明服务器并没有完全停止,而是根据需要多次尝试连接到 db。但如果数据库可用,则会写入以下日志:

2017-05-15 14:08:43.748 [error] postcode-play: 

! @7430ed7gf - Internal server error, for (GET) [/?postcode=88682&country=DE] ->

play.api.Configuration$$anon$1: Configuration error[Cannot connect to database [default]]
    at play.api.Configuration$.configError(Configuration.scala:155)
    at play.api.Configuration.reportError(Configuration.scala:808)
    at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:48)
    at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:42)
    at scala.collection.immutable.List.foreach(List.scala:392)
    at play.api.db.DefaultDBApi.connect(DefaultDBApi.scala:42)
    at play.api.db.DBApiProvider.get$lzycompute(DBModule.scala:72)
    at play.api.db.DBApiProvider.get(DBModule.scala:62)
    at play.api.db.DBApiProvider.get(DBModule.scala:58)
    at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
Caused by: java.sql.SQLTransientConnectionException: HikariPool-4 - Connection is not available, request timed out after 5001ms.
    at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:548)
    at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:186)
    at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:145)
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:83)
    at play.api.db.DefaultDatabase.getConnection(Databases.scala:142)
    at play.api.db.DefaultDatabase.getConnection(Databases.scala:138)
    at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:44)
    at play.api.db.DefaultDBApi$$anonfun$connect$1.apply(DefaultDBApi.scala:42)
    at scala.collection.immutable.List.foreach(List.scala:392)
    at play.api.db.DefaultDBApi.connect(DefaultDBApi.scala:42)
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:265)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:194)
    at org.postgresql.Driver.makeConnection(Driver.java:431)
    at org.postgresql.Driver.connect(Driver.java:247)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:95)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:101)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:341)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:193)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:430)
Caused by: java.net.ConnectException: Verbindungsaufbau abgelehnt (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.postgresql.core.PGStream.<init>(PGStream.java:62)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:194
)

服务器无法访问数据库,即使它现在可用。如果我重新启动服务器,将找到数据库并且可以使用该数据库,但数据库始终必须在启动时存在。我该如何解决这个问题,以便可以独立于数据库启动应用程序?

如果数据库在应用程序启动后变得不可用,那么在数据库再次可用后就没有问题了。它会自动重新连接。

非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

您似乎要为 Postgres 保留一些连接。这些连接必须关闭,否则 Postgres 将达到其max_connections 限制。

您可以increase max_connections,但不建议这样做,因为如果设置得太高,Postgres 的性能会下降。此外,当您使用 HikariCP 时,查看HikariCP docs 并不是一个坏主意,尤其是idleTimeoutminimumIdle 配置变量应该对您有所帮助。

如果上述方法不起作用,那么您必须准确确认与 Postgres 建立了多少连接。甚至可以检查您个人通过 SSH 或通过其他应用程序与 Postgres 进行的会话数量,而不仅仅是 Play Framework 连接的数量。

【讨论】:

以上是关于启动没有 DB 的 Java/Play2.5 REST API的主要内容,如果未能解决你的问题,请参考以下文章

Scrapy中对xpath使用re

即使 DB 关闭,Spring 应用程序也应该启动

Flyway、Spring Boot 和应用程序在没有数据库的情况下启动

有没有办法使用 quick.db 制作 discord.js 日志系统

ORA-04098 trigger 'DBBJ.DB_EV_ALTER_ST_METADATA' is invalid and failed re-validation

关于启动SpringBoot简单项目报错Error starting ApplicationContext. To display the conditions report re-run ..的问题