HttpClient hangs on socketRead0 with successfully

2019-04-07 20:37发布

In our web-application A user can submit a url. We will fetch the data and parse it server side. For each request we use an HttpClient with the following (relevant) settings

connectionManager.getParams().setConnectionTimeout(10000);
connectionManager.getParams().setSoTimeout(10000);

When I call HttpMethod.getResponseBody the status code has already been checked to be acceptable. At this point the thread hangs with this stack trace:

java.net.SocketInputStream.socketRead0 ( native code )
java.net.SocketInputStream.read ( SocketInputStream.java:150 )
java.net.SocketInputStream.read ( SocketInputStream.java:121 )
java.io.BufferedInputStream.read1 ( BufferedInputStream.java:273 )
java.io.BufferedInputStream.read ( BufferedInputStream.java:334 )
java.io.FilterInputStream.read ( FilterInputStream.java:133 )
org.apache.commons.httpclient.AutoCloseInputStream.read ( AutoCloseInputStream.java:108 )
java.io.FilterInputStream.read ( FilterInputStream.java:107 )
org.apache.commons.httpclient.AutoCloseInputStream.read ( AutoCloseInputStream.java:127 )
org.apache.commons.httpclient.HttpMethodBase.getResponseBody ( HttpMethodBase.java:690 )

I cannot discover the exact URL for which this happened (was an incident on a live environment) and I have been unable to reproduce it. I'd like to think it's simply a matter of the server we're connecting to behaving strangely, but perhaps I'm missing something. In either case, is there a way for me to prevent the blocking method call from waiting forever? The SoTimeout is also the socket read timeout? Is there another setting I'm missing?

5条回答
唯我独甜
2楼-- · 2019-04-07 20:59

We see this consistently in our implementation and it looks like http client is not handling bad servers correctly or something and it is not timing out.....I can reproduce in our setting with this databus open source project and the stack trace is a little different...

SocketInputStream.socketRead0(FileDescriptor, byte[], int, int, int) line: not available [native method]
SocketInputStream.read(byte[], int, int) line: 129
SocketInputBuffer(AbstractSessionInputBuffer).fillBuffer() line: 166
SocketInputBuffer.fillBuffer() line: 90 SocketInputBuffer(AbstractSessionInputBuffer).readLine(CharArrayBuffer) line: 281
DefaultHttpResponseParser.parseHead(SessionInputBuffer) line: 92
DefaultHttpResponseParser.parseHead(SessionInputBuffer) line: 62
DefaultHttpResponseParser(AbstractMessageParser).parse() line: 254
DefaultClientConnection(AbstractHttpClientConnection).receiveResponseHeader() line: 289 DefaultClientConnection.receiveResponseHeader() line: 252
BasicPooledConnAdapter(AbstractClientConnAdapter).receiveResponseHeader() line: 219 HttpRequestExecutor.doReceiveResponse(HttpRequest, HttpClientConnection, HttpContext) line: 300 HttpRequestExecutor.execute(HttpRequest, HttpClientConnection, HttpContext) line: 127
DefaultRequestDirector.tryExecute(RoutedRequest, HttpContext) line: 712 DefaultRequestDirector.execute(HttpHost, HttpRequest, HttpContext) line: 517
DefaultHttpClient(AbstractHttpClient).execute(HttpHost, HttpRequest, HttpContext) line: 906 DefaultHttpClient(AbstractHttpClient).execute(HttpUriRequest, HttpContext) line: 805
ReadAggregations.processAggregation(String, Counter, Counter, Counter, Counter) line: 153
ReadAggregations.start() line: 96
ReadAggregations.main(String[]) line: 70

查看更多
Luminary・发光体
3楼-- · 2019-04-07 21:02

When I call HttpMethod.getResponseBody the status code has already been checked to be acceptable. At this point the thread hangs

Looks like you have a problem with synchronizing the calls ... you should ensure that the method

HttpMethod.getResponseBody

is called sequentially or should use a mutex (semaphore ) for the part that changes the status code

Also you should decrease your timeout limit to prevent hangs.

查看更多
Ridiculous、
4楼-- · 2019-04-07 21:12

HttpClient distinguishes between connection and request. setSoTimeout will configure the connection socket timeout while setConnectionTimeout will configure both the timeout for the connection manager (how long to wait for a connection) and for the establishment of the connection itself. In the code you provided, you are not setting any timeout for the socket used for the request itself, and unfortunately, HttpClient has no timeout by default for that.

Here's how I do it in v4.4.1:

// Configure the socket timeout for the connection, incl. ssl tunneling
connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(200);
connManager.setDefaultMaxPerRoute(100);

SocketConfig sc = SocketConfig.custom()
    .setSoTimeout(soTimeoutMs)
    .build();

connManager.setDefaultSocketConfig(sc);

HttpClient client = HttpClients.custom()
            .setConnectionManager(connManager)
            .setConnectionManagerShared(true)
            .build();

// configure the timeouts (socket and connection) for the request
RequestConfig.Builder config = = RequestConfig.copy(RequestConfig.DEFAULT);
config.setConnectionRequestTimeout(connectionTimeoutMs);
config.setSocketTimeout(socketTimeoutMs);

HttpRequestBase req = new HttpGet(uri);
req.setConfig(config.build());

client.execute(req);
查看更多
小情绪 Triste *
5楼-- · 2019-04-07 21:17

I have all the timeouts setup just fine but I found out we have on url that does http chunking but sends no results(works fine in chrome, but in http client it hangs forever even with the timeout set). Luckily I own the server and just return some garbage and it no longer hangs. This seems like a very unique bug in that http client does not handle some kind of empty chunking case well(though I could be way off)....I just know it hangs every time on that same url with empty data and that url is http chunking csv download back to our http client.

查看更多
看我几分像从前
6楼-- · 2019-04-07 21:19

You can try to abort the request with HttpUriRequest#abort(), see https://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/methods/HttpUriRequest.html#abort%28%29. However, setting a timemout that requires no intercepting would be nicer. Here is a related question: Setting time out in apache http client

查看更多
登录 后发表回答