我正在使用Amazon RDS服务托管PostreSql,该PostreSql用作Java应用程序的数据库。应用程序启动后,它能够按预期执行查询,直到我停止交互几分钟后再尝试再次执行任何查询。在这种情况下,我得到以下异常:
WARNING: Validating connection.
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:327)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at org.postgresql.jdbc.PgConnection.isValid(PgConnection.java:1311)
at org.apache.commons.dbcp2.DelegatingConnection.isValid(DelegatingConnection.java:897)
at org.apache.commons.dbcp2.PoolableConnection.validate(PoolableConnection.java:270)
at org.apache.commons.dbcp2.PoolableConnectionFactory.validateConnection(PoolableConnectionFactory.java:630)
at org.apache.commons.dbcp2.PoolableConnectionFactory.validateObject(PoolableConnectionFactory.java:648)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:472)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:349)
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:753)
Caused by: java.net.SocketException: Operation timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:140)
at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:109)
at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:67)
at org.postgresql.core.PGStream.receiveChar(PGStream.java:288)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1962)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)
在Amazon RDS PostgreSQL上,我看到以下错误:
2020-04-09 19:01:11 UTC::[]:LOG: could not receive data from client: Connection timed out
2020-04-09 19:04:27 UTC::@:[]:LOG: checkpoint starting: time
2020-04-09 19:04:28 UTC::@:[]:LOG: checkpoint complete: wrote 1 buffers (0.0%); 0 WAL file(s) added, 0 removed, 1 recycled; write=0.143 s, sync=0.001 s, total=0.154 s; sync files=1, longest=0.001 s, average=0.001 s; distance=16377 kB, estimate=16396 kB
2020-04-09 19:08:15 UTC::LOG: could not receive data from client: Connection timed out
关于解决该问题的任何想法?
我在这里看到一个潜在的问题,您的连接池中的连接到Postgres DB的连接可能用完了,这可能是因为现有的连接可能在数据库事务处理后没有关闭,并且不会被新的传入数据库重新使用交易。尝试使用pgbouncer解决此问题。我的猜测是看到您的日志
我想您有一个(虚拟)网络组件,例如路由器,负载平衡器,状态防火墙等,它们决定在X秒钟后可以删除您的连接以节省一些宝贵的内存。但是,这不会通知双方TCP连接(数据库或Java应用程序),因此一段时间后,他们将注意到它们不再相互连接。
如果您无法更改网络组件的行为,这些行为会无声地杀死您的连接,则您可以从以下选项中进行选择:
使用操作系统中的TCP功能(TCP KeepAlive),方法是:
不使用连接池(但这对性能不利,请参阅:this answer for more details]
我以前曾经遇到过这个问题,这让我发疯。最终问题是因为防火墙在没有通知后端的情况下停止了超过30分钟的任何空闲连接]