Apache HttpClient 4.5:连接重置

Posted

技术标签:

【中文标题】Apache HttpClient 4.5:连接重置【英文标题】:Apache HttpClient 4.5: Connection Resets 【发布时间】:2017-08-04 20:13:57 【问题描述】:

我正在使用 httpClient 4.5 版连接我们的外部供应商网站。我们不需要任何连接池或持久连接,所以我使用 BasicHttpClientConnectionManager 来创建 HttpClient。

这适用于最少数量的请求,但如果我以 1TPS 测试 1 小时,在测试结束时,我们开始看到间歇性连接重置。 (猜测请求数 > 100)

处理对 s->https://apiURL:443 的请求时捕获的 I/O 异常 (java.net.SocketException):连接重置

请在下面找到用于建立连接的代码sn-p。

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), new X509TrustManager[]  new DefaultTrustManager() , new SecureRandom());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]  "TLSv1.2" , null,SSLConnectionSocketFactory.getDefaultHostnameVerifier());
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslsf).register("http", new PlainConnectionSocketFactory()).build();

HttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry);
HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(1, false);

RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(Integer.parseInt(30000)).setConnectTimeout(Integer.parseInt(30000)).setConnectionRequestTimeout(30000).setCookieSpec(CookieSpecs.STANDARD).build();

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(defaultRequestConfig).setRetryHandler(retryHandler).evictExpiredConnections().build();

HttpPost httpPost = new HttpPost(<endpoint>);
httpPost.setEntity(new UrlEncodedFormEntity(requestData));
httpResponse = httpClient.execute(httpPost);

我看到针对报告的类似问题的修复已在 4.5 版中可用。 (参考:https://issues.apache.org/jira/browse/HTTPCLIENT-1655)由Oleg提供

如果是这样,不知道为什么我仍然面临这个问题。有人可以帮忙吗?

谢谢!

【问题讨论】:

是否考虑过对端端点重置连接的可能性? 感谢Oleg 的回复。从我们在这里与网络团队运行的跟踪中可以看出,当目标主机向我们请求 ACK 时,源,即我们的服务器一直在发送大量重置 (RST)。所以,这就是我试图弄清楚这是否是我们使用的 HttpClient 的问题的原因。 此时,我们所做的就是将重试次数增加到 3(使用 DefaultHttpRequestRetryHandler),因为我们注意到一些被连接重置错误命中的请求在重试。但是,对于我们面临的问题,这似乎不是一个合适的解决方案。 怀疑服务器无法跟上负载并丢弃无法提供服务的连接。对于安全和幂等的方法,重试策略应该是一个完美的解决方案。 谢谢Oleg,我猜你是对的,我们也得出了类似的结论。如果我可以从与客户端的连接的角度尝试其他任何事情,请告诉我。 【参考方案1】:

嗨Oleg,

当我仍然看到上面发布的连接重置错误时,我一直在使用 httpclient 版本 4.5.3。

后来注意到重置问题的修复已提交到版本 4.5.1 (https://issues.apache.org/jira/browse/HTTPCLIENT-1655)。因此,只是尝试更新该特定版本,运行测试并且不再看到连接重置错误。 我原以为从 4.5.1 开始的更高版本也应该提供此修复程序。但是,我猜它在更高版本中以某种方式错过了,已经证实它肯定仍然是版本 4.5.3 的问题。

因此,结论是使用 httpclient 4.5.1 jar 修复了连接重置错误。

谢谢!

【讨论】:

我资助它有点难以置信,但就这样吧。 是的,我也没有考虑过这种可能性。而且,如果我没有尝试使用不同版本运行多轮测试,我就不会那么肯定了。这只是一个试验,但我很高兴修复它。希望您也将修复添加到更高版本。 问题是我不知道要解决什么问题,因为 HTTPCLIENT-1655 自 4.5.1 以来的所有 4.5.x 版本中都存在。我做了仔细检查。

以上是关于Apache HttpClient 4.5:连接重置的主要内容,如果未能解决你的问题,请参考以下文章

java: apache HttpClient > 如何禁用重试

HttpClient(4.5) post get https 实例

最近使用httpclient总结的几条注意事项

使用Apache HttpClient 4.x进行异常重试

HttpClient工具类

org.apache.httpcomponents:httpclient 工具类