在一段时间间隔后调用 API 时第一次获取连接重置异常
Getting Connection reset exception first time while calling API after sometime of interval
我们正在对 API 进行 post 调用,当我们在一段时间间隔后开始调用此 API 时(在我们的例子中大部分时间是 10 分钟,很少我们get if interval is 5 mins) 第一次尝试时我们得到 Connection reset exception,然后立即调用的其余部分工作正常,但如果调用此 API 的间隔为 10 分钟然后再次调用,我们得到这样该间隔后第一次调用的异常。
我们正在使用 Java spring-boot Restamplate 进行 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
重新模板配置
@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 节 - 连接保持活动策略:
Keep-Alive
header 在响应中
If the Keep-Alive header is not present in the response, HttpClient
assumes the connection can be kept alive indefinitely.
我猜您的 api 响应中有一个 Keep-Alive
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.
我们正在对 API 进行 post 调用,当我们在一段时间间隔后开始调用此 API 时(在我们的例子中大部分时间是 10 分钟,很少我们get if interval is 5 mins) 第一次尝试时我们得到 Connection reset exception,然后立即调用的其余部分工作正常,但如果调用此 API 的间隔为 10 分钟然后再次调用,我们得到这样该间隔后第一次调用的异常。 我们正在使用 Java spring-boot Restamplate 进行 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
重新模板配置
@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 节 - 连接保持活动策略:
Keep-Alive
header 在响应中
If the Keep-Alive header is not present in the response, HttpClient assumes the connection can be kept alive indefinitely.
我猜您的 api 响应中有一个 Keep-Alive
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.