我对以下案例有点困惑。
我在主机A上运行了一个Postgres
服务器,在主机B上运行了一个基于java的客户端。客户端使用org.postgresql.Driver
JDBC驱动程序(版本9.1-901.jdbc3)。
有时在执行长时间运行的存储过程时,我会得到异常“java.net.SocketException: Socket closed
”。我正在使用org.apache.commons.dbcp.BasicDataSource
进行检索
连接。
DBCP池配置了默认选项。
我得到了tcp dump,以便弄清楚哪一侧(客户端或服务器)套接字正在关闭;
这就是我所拥有的:
1. Client B sends a test query message when tries to borrow connection from dbcp pool ("Select 1")
2. Server A sends successful response back (Type: Command completion, Ready for query)
3. Client B sends ACK message in response on server A response (see the item 2).
4. Client B sends query message to the server A.
5. Server A sends ACK message in response on client Query message (see the item 4).
6. Client B sends terminating message (Type : Termination) after some time passed (from 3 to 10 or sometimes even more minutes).
7 Client B sends FIN ACK message to the server.
8. Server A sends back ACK on termination message.
9. Server A sends ACK on (FIN, ACK) message (item 7).
10. Server A sends back a response on the client query (from item 4) Type: Row description Columns: 40.
11. Client B sends RST message (reset).
12. Server A continues sending response on the query Type: Data row Length: 438 Columns 40 and so on.
13 Client B sends RST message (reset) again.
14. Server A continues sending response on the query Type: Data row Length: 438 Columns 40 and so on.
15. Client B sends RST message (reset).
之后,通信似乎已经完成。
在第6项之后,在我的客户端日志中,我得到了如下的异常:
Caused by: java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:145)
at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:114)
at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73)
at org.postgresql.core.PGStream.ReceiveChar(PGStream.java:274)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1661)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
请你帮我弄清楚这种失败的原因。 (这个错误每10个成功案例发生一次。)
答案 0 :(得分:0)
我们遇到了类似的问题,它是由服务器和客户端之间的防火墙或连接跟踪路由器引起的。
我猜你在服务器端拿了tcpdump。查询运行相当长的时间,连接上没有流量。防火墙在打开的连接上有一个计时器;它会过期,防火墙会关闭与服务器的连接,也会关闭到客户端。在服务器端捕获时,看起来客户端正在关闭连接。
您可以通过在服务器端捕获时在客户端同时捕获来验证这一点 - 在客户端,它看起来像服务器已关闭连接,而在服务器端看起来服务器正在关闭连接。实际上,防火墙正在向两个方向关闭它。
为防止这种情况发生,您可以设置tcp_keepalives_idle,tcp_keepalives_interval和/或tcp_keepalives_count(如果您的操作系统支持TCP Keepalive)。或者,您必须更改防火墙上的设置。