我们在请求接口的时候容易出现请求超时的现象,出现这一问题的原因可能是接口确实挂了,也可能是接口还没有来的及响应,我们程序里面已经出现了请求超时的现象
问题描述:
通常会出现以下的报错:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(SocketInputStream.java)
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.apache.http.impl.conn.LoggingInputStream.read(LoggingInputStream.java:84)
at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:282)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:165)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
结合接口日志的打印,我判断是第二种现象,就是接口还没有返回信息,我程序这边就出现了超时的报错。那么如何解决,我们只有增加接口的请求等待时间
问题解决:
private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
public static String postGeneralUrl(String url, String contentType, String jsonParam, String encoding, int reSend) {
logger.info("当前请求接口地址:{}",jsonParam.toString());
// 声明返回结果
String result = "";
// 开始请求API接口时间
long startTime = System.currentTimeMillis();
// 请求API接口的响应时间
long endTime = 0L;
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
HttpClient httpClient = null;
try {
contentType = contentType == null ? "application/x-www-form-urlencoded" : contentType;
// 创建连接
httpClient = HttpClientFactory.getInstance().getHttpClient();
// 设置请求头和报文
HttpPost httpPost = HttpClientFactory.getInstance().httpPost(url);
Header header = new BasicHeader("Accept-Encoding", null);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
httpPost.setConfig(requestConfig);
httpPost.addHeader(header);
httpPost.addHeader("Content-Type", contentType);
List<NameValuePair> list = new LinkedList<>();
list.add(new BasicNameValuePair("params", jsonParam));// pageHelper放在body中传过去
// 使用URL实体转换工具
UrlEncodedFormEntity entityParam = new UrlEncodedFormEntity(list, "UTF-8"); // 使用 UrlEncodedFormEntity 来设置
// // body,消息体内容
httpPost.setEntity(entityParam);
logger.info("请求{}接口的参数为{}", url, jsonParam);
httpResponse = httpClient.execute(httpPost);
httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
} catch (SocketTimeoutException es) {
endTime = System.currentTimeMillis();
result = "网络连接异常,请检查网络或者开票服务是否正常启动";
logger.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
logger.error("请求{}接口出现异常", url, es);
return result;
} catch (Exception e) {
logger.error("请求{}接口出现异常", url, e);
} finally {
try {
EntityUtils.consume(httpEntity);
} catch (IOException e) {
e.printStackTrace();
}
}
// 请求接口的响应时间
endTime = System.currentTimeMillis();
logger.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
return result;
}
其中主要是这部分代码:
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
httpPost.setConfig(requestConfig);
当然这个设置和使用的 http.client 版本也有一定的关系
当前我使用的版本是:
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
希望对你有所帮助