我们正在对 API 进行后期调用,当我们在一段时间后开始调用此 API 时(在我们的案例中大部分时间为 10 分钟,如果间隔为 5 分钟,我们很少得到),我们会在第一次尝试时收到连接重置异常,然后其余的即时调用工作正常,但是如果调用此 API 的间隔为 10 分钟,然后再次调用,我们会在该间隔后的第一次调用中得到此类异常。
我们正在使用 Java spring-boot Resttamplate 进行 API 调用并使用 Apache httpclient-4.5.2
apache 日志 "[read] I/O error: Read timed out"
Java 日志 Connection reset; nested exception is java.net.SocketException: Connection reset
Resttamplate 配置
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
return restTemplate;
}
@Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setHttpClient(httpClient());
return clientHttpRequestFactory;
}
@Bean
public CloseableHttpClient httpClient() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(180000)
.setConnectTimeout(180000)
.setSocketTimeout(180000).build();
return HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(poolingConnectionManager())
// .setKeepAliveStrategy(connectionKeepAliveStrategy())
.build();
}
@Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() {
PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
poolingConnectionManager.setMaxTotal(50);
return poolingConnectionManager;
}
如果我们在 HttpClients.custom() 中添加 set connectionKeepAliveStrategy 如下所述,我们将不会遇到任何此类异常。@Bean
public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
return new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
HeaderElementIterator it = new BasicHeaderElementIterator
(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
HeaderElement he = it.nextElement();
String param = he.getName();
String value = he.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000;
}
}
return 20000;
}
};
}
不知道为什么这种异常会随着 connectionKeepAliveStrategy 消失。它在这当中起什么作用?提前致谢。
最佳答案
查询 these两个重要的点:
栏目 2.6 - 连接保持 Activity 策略 :
Keep-Alive
响应中的 header If the Keep-Alive header is not present in the response, HttpClient assumes the connection can be kept alive indefinitely.
我猜有一个
Keep-Alive
api 响应中的 header ,值为 600 秒。 keep-alive
策略:However, many HTTP servers in general use are configured to drop persistent connections after a certain period of inactivity in order to conserve system resources, quite often without informing the client. In case the default strategy turns out to be too optimistic, one may want to provide a custom keep-alive strategy.
关于java - 在一段时间后调用 API 时第一次获取连接重置异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62552480/