HttpClient 4 静静地挂在 socketRead 上
HttpClient 4 silently hangs on socketRead
我有一个应用程序使用保持活动连接连续轮询远程 HTTP API。
很少但偶尔应用程序会在工作一段时间后静默挂起。
套接字仍然打开,但是远程APIreturns没有数据。
Httpclient 有套接字超时和连接超时,但是我如何处理我们已经连接的超时,套接字仍然打开但服务器 returns 没有数据?
netstat -np
进程:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 redactedlocalip:31136 redactedforeignip:80 ESTABLISHED 11145/java
我的 http 客户端:
SocketConfig socketConfig = SocketConfig.copy(SocketConfig.DEFAULT).setSoTimeout(25000).build();
BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager();
connectionManager.setSocketConfig(socketConfig);
return HttpClients
.custom()
.setUserAgent(USER_AGENT)
.setConnectionManager(connectionManager)
.setRetryHandler(new DefaultHttpRequestRetryHandler())
.build();
主线程转储:
"main" #11 prio=5 os_prio=0 tid=0x00007f6b802ce800 nid=0x2b9f runnable [0x00007f6b675ec000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:139)
at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:155)
at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:284)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261)
at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:165)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at redacted.app.code.executemyRequest(MyClass.java:117)
我使用的是 maven 的最新版本 "org.apache.httpcomponents:httpclient:4.5"
问题是 HTTP 服务器表现不佳,它从未响应某些请求但继续保持 TCP 连接和 send/receive 保持活动数据包。
Apache HTTPClient 没有任何内置超时来处理这些情况,解决方案是在指定的等待时间后手动调用 HTTPRequest$abort() 方法。
它当然需要从不同的线程调用,因为调用线程将被阻塞等待。
我有一个应用程序使用保持活动连接连续轮询远程 HTTP API。
很少但偶尔应用程序会在工作一段时间后静默挂起。
套接字仍然打开,但是远程APIreturns没有数据。
Httpclient 有套接字超时和连接超时,但是我如何处理我们已经连接的超时,套接字仍然打开但服务器 returns 没有数据?
netstat -np
进程:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 redactedlocalip:31136 redactedforeignip:80 ESTABLISHED 11145/java
我的 http 客户端:
SocketConfig socketConfig = SocketConfig.copy(SocketConfig.DEFAULT).setSoTimeout(25000).build();
BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager();
connectionManager.setSocketConfig(socketConfig);
return HttpClients
.custom()
.setUserAgent(USER_AGENT)
.setConnectionManager(connectionManager)
.setRetryHandler(new DefaultHttpRequestRetryHandler())
.build();
主线程转储:
"main" #11 prio=5 os_prio=0 tid=0x00007f6b802ce800 nid=0x2b9f runnable [0x00007f6b675ec000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:139)
at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:155)
at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:284)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261)
at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:165)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at redacted.app.code.executemyRequest(MyClass.java:117)
我使用的是 maven 的最新版本 "org.apache.httpcomponents:httpclient:4.5"
问题是 HTTP 服务器表现不佳,它从未响应某些请求但继续保持 TCP 连接和 send/receive 保持活动数据包。
Apache HTTPClient 没有任何内置超时来处理这些情况,解决方案是在指定的等待时间后手动调用 HTTPRequest$abort() 方法。
它当然需要从不同的线程调用,因为调用线程将被阻塞等待。