java - 在一段时间后调用 API 时第一次获取连接重置异常
问题描述
我们正在对 API 进行后期调用,当我们在一段时间间隔后开始调用这个 API 时(在我们的例子中,大部分时间是 10 分钟,如果间隔是 5 分钟,我们很少会得到)我们第一次尝试得到连接重置异常,然后其余的立即调用工作正常,但如果调用此 API 的间隔为 10 分钟,然后再次调用,我们会在该间隔之后的第一次调用中遇到此类异常。我们正在使用 Java spring-boot Resttamplate 进行 API 调用并使用 Apache httpclient-4.5.2
阿帕奇日志
"[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 消失。它在其中的作用是什么?提前致谢。
解决方案
检查以下两个要点:
第2.6 节 - 连接保持活动策略:
Keep-Alive
响应中的标头
如果响应中不存在 Keep-Alive 标头,则 HttpClient 假定连接可以无限期地保持活动状态。
我猜Keep-Alive
你的 api 响应中有一个值为 600 秒的标头。
- 自定义
keep-alive
策略:
然而,许多一般使用的 HTTP 服务器被配置为在一段时间不活动后丢弃持久连接,以节省系统资源,通常不会通知客户端。如果默认策略过于乐观,可能需要提供自定义的保持活动策略。
推荐阅读
- machine-learning - 我的简单 Julia-Flux 密集模型中出现奇怪且无信息的错误
- java - 无法在 JAVA EE 中正确读取 ArrayList
- solr - Solr - 多边形搜索 - 按距离从多边形中心对结果进行排序
- android - 从 Zygote 进程创建应用程序时会克隆哪些信息?
- maven - 无法使用 IntelliJ 解析 org.cytoscape
- java - HTMLUnit input.click() 没有返回点击应该加载的站点
- java - 如何针对其中的两个元素(两列)对类型为类的数组列表进行排序
- javascript - 如何修复 Seek Command 使歌曲回到开头 - Discord.js
- json - 如何使用相同的键在嵌套的 json 对象中构造数组
- android - 签署与 AAB 相同的 APK