SocketTimeoutException: Read timed out httpclient

5
我有一个REST服务,每天提供约20M请求。我遇到了以下异常。这个问题是间歇性的,我无法将这个问题与请求量联系起来。即使在周末请求量很小的时候,我也遇到了这个异常。我通过检查setStaleConnectionCheckEnabled确保没有过期的连接。我正在使用httpclient 4.3.4。
更新:经过进一步分析,我发现以下更多细节:
从日志中可以看出,大部分请求在300毫秒内得到了响应,但客户端连接服务本身需要时间,当收到响应时,已经超过了6秒的阈值,并运行到了读取超时异常。
getCause(): java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:891)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
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.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:167)
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:71)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:220)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:164)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:139)
at com.sample.SampleClient.doGet(SampleClient.java:137)

客户:

public MyRespBean doGet(String host, String path, List<NameValuePair> nameValuePairs, Map<String, String> headers, AuthParams authParams)
throws URISyntaxException, IOException
{
  RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(6000).setConnectTimeout(6000).setStaleConnectionCheckEnabled(true).build();
  CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
  URI uri = buildUri(host, path, nameValuePairs);
  HttpGet httpGet = new HttpGet(uri);
  httpGet.setHeader("Connection", "close");
  addHeaders(httpGet, headers, authParams);
 **//Error occurs at the following line**
 MyRespBean respBean = (MyRespBean)httpClient.execute(httpGet, new SimpleResponseHandler());
  httpClient.close();
  return respBean;
}

一般来说,读取超时时间为六秒太短了。 - user207421
1个回答

1

您是该服务的所有者吗?

如果是的话,我会检查为什么在回复时数据包之间有超过6秒的暂停:根据异常判断,连接成功了。

可能的原因:定期缓慢的连接或服务端上非常长的full GC。或者甚至是长时间的周期性预热阶段(我不知道服务实现的细节,但可能对于某些特定请求,服务需要花费超过6秒的时间来准备响应)- 换句话说,任何导致您的服务在6秒内无法回答的情况。


是的,我拥有服务和客户端。从日志中可以看到,服务在300毫秒内响应,但连接到服务本身需要时间,等到收到响应时,已经超过了阈值6秒,并遇到了读取超时异常。 - Pankaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接