【问题标题】:Socket timeout not working when uprading to postgres jdbc driver 42.2.10+升级到 postgres jdbc 驱动程序 42.2.10+ 时,套接字超时不起作用
【发布时间】:2020-10-22 22:57:09
【问题描述】:

我有一个作为 WAR 文件部署到 Tomcat 中的 java 应用程序。将 Postgres DB 的数据源查找为 JNDI 资源,并使用 Tomcat 的默认连接池 - DBCP 2。context.xml 中的Resource 定义如下

<Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"
              maxTotal="50" maxIdle="15" maxWaitMillis="10000"
              username="test" password="test"
              driverClassName="org.postgresql.Driver"
              defaultReadOnly="true"
              url="jdbc:postgresql://localhost:5432/test?socketTimeout=45"
              validationQuery="SELECT 1" testOnBorrow="true" />

有一个名为DbConnectionChecker 的类,它使用Executors.newSingleThreadScheduledExecutor() 执行程序每3 秒检查一次DB 是否处于活动状态。

public class DbConnectionChecker {

    private static final Logger LOG = LoggerFactory.getLogger(DbConnectionChecker.class);
    private final ScheduledExecutorService taskExecutor;

    private String name;

    private DataSource dataSource;

    private volatile boolean enabled = false;

    public DbConnectionChecker(String name, DataSource dataSource, ScheduledExecutorService taskExecutor, Runnable onConnectionOk,
            Runnable onConnectionNoOk) {
        this.name = name;
        this.dataSource = dataSource;
        this.taskExecutor = taskExecutor;
        this.taskExecutor.scheduleAtFixedRate(() -> pingConnection(onConnectionOk, onConnectionNoOk), 0l, 3000l, TimeUnit.MILLISECONDS);
    }

    public void start() {
        LOG.info("Starting to check {} connection", name);
        enabled = true;

    }

    public void shutdown() {
        taskExecutor.shutdown();
    }

    public void stop() {
        enabled = false;
    }

    public void pingConnection(Runnable onConnectionOk, Runnable onConnectionNoOk) {
        if (!enabled) {
            return;
        }
        try (Connection connection = dataSource.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT 1")) {
            preparedStatement.executeQuery();
            LOG.info("Connection {} OK...", name);
            onConnectionOk.run();
        } catch (Exception e) {
            LOG.info("Connection {} couldn't be created...", name);
            onConnectionNoOk.run();
        }
    }
}

当一切开始时,我可以 sse 一个日志行 Connection test OK...,每 3 秒打印一次日志。 到目前为止一切顺利。

现在我尝试模拟网络故障和无法访问的数据库。我将更改 iptables 并切断与本地 Postgres 的连接。

sudo iptables -A INPUT -i lo -p tcp --dport 5432 -j DROP

使用 postgres-42.2.9 一切正常,我将在一分钟左右得到一个日志行 Connection test couldn't be created...。 升级到 postgres-42.2.10+ 后 - 我已经测试了所有最新的次要版本,这会中断。 Executor 的线程卡在某个套接字调用中并在那里等待 aprox。发布前30分钟。相关的堆栈跟踪在这里

pool-14-thread-1@12955" prio=5 tid=0x45 nid=NA runnable"pool-14-thread-1@12955" prio=5 tid=0x45 nid=NA runnable  java.lang.Thread.State: RUNNABLE   at
java.net.SocketInputStream.socketRead0(SocketInputStream.java:-1)   at
java.net.SocketInputStream.socketRead(SocketInputStream.java:116)   at
java.net.SocketInputStream.read(SocketInputStream.java:171)   at
java.net.SocketInputStream.read(SocketInputStream.java:141)   at
sun.security.ssl.InputRecord.readFully(InputRecord.java:465)   at
sun.security.ssl.InputRecord.read(InputRecord.java:503)   at
sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)   - locked <0x3e55> (a java.lang.Object)   at
sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:933)   at
sun.security.ssl.AppInputStream.read(AppInputStream.java:105)   - locked <0x3e37> (a sun.security.ssl.AppInputStream)   at
org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:161)   at
org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:128)   at
org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:113)   at
org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73)   at
org.postgresql.core.PGStream.receiveChar(PGStream.java:370)   at
org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2043)   at
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312)   - locked <0x3e3a> (a org.postgresql.core.v3.QueryExecutorImpl)   at
org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)   at
org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)   at
org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:153)   at
org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:103)   at
org.apache.tomcat.dbcp.dbcp2.PoolableConnection.validate(PoolableConnection.java:287)   at
org.apache.tomcat.dbcp.dbcp2.PoolableConnectionFactory.validateConnection(PoolableConnectionFactory.java:630)   at
org.apache.tomcat.dbcp.dbcp2.PoolableConnectionFactory.validateObject(PoolableConnectionFactory.java:648)   at
org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:476)   at
org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:353)   at
org.apache.tomcat.dbcp.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134)   at
org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:753)   at
com...db.DbConnectionChecker.pingConnection(DbConnectionChecker.java:49)   at
com...db.DbConnectionChecker.lambda$new$0(DbConnectionChecker.java:28)   at
com...db.DbConnectionChecker$$Lambda$250.1931785101.run(Unknown Source:-1)   at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)   at
java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308)   at
java.util.concurrent.FutureTask.runAndReset(FutureTask.java:-1)   at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)   at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)   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) 

最新的 postgres 驱动程序有问题吗?是否有任何超时 - 默认设置,我不知道?

【问题讨论】:

    标签: java postgresql tomcat


    【解决方案1】:

    我在 pgjdbc 的 github 问题中得到了答案。可以参考this issue

    【讨论】:

      猜你喜欢
      • 2012-11-03
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      • 2015-04-07
      • 2014-01-13
      • 2015-09-11
      • 2017-11-14
      • 1970-01-01
      相关资源
      最近更新 更多