java - 使用hikari连接池时如何解决 "Socket read timed out"

标签 java database playframework oracle12c socket-timeout-exception

我正在使用 play 框架(版本 2.8.0)、java(版本 1.8)和 Oracle 数据库(版本 12C)开发一个应用程序。

一天内只有零次或一次对数据库的点击,我收到以下错误。

java.sql.SQLRecoverableException: IO Error: Socket read timed out
    at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:919)
    at oracle.jdbc.driver.PhysicalConnection.close(PhysicalConnection.java:2005)
    at com.zaxxer.hikari.pool.PoolBase.quietlyCloseConnection(PoolBase.java:138)
    at com.zaxxer.hikari.pool.HikariPool.lambda$closeConnection$1(HikariPool.java:447)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketTimeoutException: Socket read timed out
    at oracle.net.nt.TimeoutSocketChannel.read(TimeoutSocketChannel.java:174)
    at oracle.net.ns.NIOHeader.readHeaderBuffer(NIOHeader.java:82)
    at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:139)
    at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:101)
    at oracle.net.ns.NIONSDataChannel.readDataFromSocketChannel(NIONSDataChannel.java:80)
    at oracle.jdbc.driver.T4CMAREngineNIO.prepareForReading(T4CMAREngineNIO.java:98)
    at oracle.jdbc.driver.T4CMAREngineNIO.unmarshalUB1(T4CMAREngineNIO.java:534)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:485)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:252)
    at oracle.jdbc.driver.T4C7Ocommoncall.doOLOGOFF(T4C7Ocommoncall.java:62)
    at oracle.jdbc.driver.T4CConnection.logoff(T4CConnection.java:908)
    ... 6 common frames omitted

db {
default {
driver=oracle.jdbc.OracleDriver
url="jdbc:oracle:thin:@XXX.XXX.XXX.XX:XXXX/XXXXXXX"
username="XXXXXXXXX"
password="XXXXXXXXX"
hikaricp {
  dataSource {
    cachePrepStmts = true
    prepStmtCacheSize = 250
    prepStmtCacheSqlLimit = 2048
      }
     }
  }
}

这似乎是由于数据库连接不活动造成的,我该如何解决这个问题? 如果需要任何其他信息,请告诉我?

最佳答案

您可以为 JDBC 启用 TCP keepalive - 通过设置 JVM 指令或通过在连接字符串中添加“ENABLE=BROKEN”来启用。

但是:

  • 通常,当 TCP 连接处于非 Activity 状态超过一小时时,Cisco/Juniper 就会切断 TCP 连接。
  • Linux 内核在两小时后(tcp_keepalive_time)开始发送 keepalive 探测。因此,如果您决定打开 tcp keepalive,您还需要 root 来将此内核可调值更改为较低值(10-15 分钟)
  • 此外,默认情况下,HikariCP 不应使任何连接保持打开状态超过 30 分钟。

因此,如果您的固件、Linux 内核和 HikariCP 都使用默认设置,那么您的系统中不应出现此错误。

参见 HikariCP official documentation

maxLifetime: This property controls the maximum lifetime of a connection in the pool. An in-use connection will never be retired, only when it is closed will it then be removed. On a connection-by-connection basis, minor negative attenuation is applied to avoid mass-extinction in the pool. We strongly recommend setting this value, and it should be several seconds shorter than any database or infrastructure imposed connection time limit. A value of 0 indicates no maximum lifetime (infinite lifetime), subject of course to the idleTimeout setting. The minimum allowed value is 30000ms (30 seconds). Default: 1800000 (30 minutes)

关于java - 使用hikari连接池时如何解决 "Socket read timed out",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62632709/

相关文章:

javascript - Play 框架 websocket 发生这种情况时不会向前端发送消息

java - 数据库 'default' 需要进化!当尝试使用 play Framework 2.7.0 和 Ebean 连接到 MySQL 时

java - 自定义模型的缓存/持久化的最佳方法

java - 如何让 Java 注册一个带空格的字符串输入?

php - mysql_query 不成功。数据库没有收到任何数据

backbone.js - 保护 Play 的 REST API

java - 如何让鼠标监听器通知在假想三角形内单击?

java - 添加后的意外结果

mysql - 设计一个字段有多个值的Mysql数据库

mysql - 定制电脑商店数据库