升级到Postgres jdbc驱动程序42.2.10 +

时间:2020-07-02 10:53:10

标签: java postgresql tomcat

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

<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();
        }
    }
}

一切开始后,我可以选择一条日志行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 +之后-我已经测试了所有最新的次要版本,但此操作中断了。执行程序的线程卡在某些套接字调用中,并在那里等待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驱动程序是否存在问题?是否有我不知道的超时-默认设置?

1 个答案:

答案 0 :(得分:1)

我在pgjdbc的github问题中得到了答案。您可以引用this issue