在我的测试应用程序中,我使用Apache HttpClient对同一主机执行连续的HttpGet请求,但是在收到下一个请求时,事实证明先前的HttpConnection已关闭,并且创建了新的HttpConnection。
我使用HttpClient的相同实例,并且不关闭响应。从每个实体中,我得到InputStream,使用Scanner读取它,然后关闭Scanner。我已经测试过KeepAliveStrategy,它返回true。请求之间的时间不超过keepAlive或connectionTimeToLive的持续时间。
谁能告诉我这种行为的原因是什么?
更新
我找到了解决方案。为了使HttpConnecton保持活动状态,必须在构建HttpClient时设置HttpClientConnectionManager。我使用了BasicHttpClientConnectionManager。
ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context)
{
long keepAlive = super.getKeepAliveDuration(response, context);
if (keepAlive == -1)
keepAlive = 120000;
return keepAlive;
}
};
HttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager();
try (CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager) // without this setting connection is not kept alive
.setDefaultCookieStore(store)
.setKeepAliveStrategy(keepAliveStrat)
.setConnectionTimeToLive(120, TimeUnit.SECONDS)
.setUserAgent(USER_AGENT)
.build())
{
HttpClientContext context = new HttpClientContext();
RequestConfig config = RequestConfig.custom()
.setCookieSpec(CookieSpecs.DEFAULT)
.setSocketTimeout(10000)
.setConnectTimeout(10000)
.build();
context.setRequestConfig(config);
HttpGet httpGet = new HttpGet(uri);
CloseableHttpResponse response = httpClient.execute(httpGet, context);
HttpConnection conn = context.getConnection();
HttpEntity entity = response.getEntity();
try (Scanner in = new Scanner(entity.getContent(), ENC))
{
// do something
}
System.out.println("open=" + conn.isOpen()); // now open=true
HttpGet httpGet2 = new HttpGet(uri2); // on the same host with other path
// and so on
}
更新2
通常,用
conn.isOpen()
检查连接不是检查连接状态的正确方法,因为:“内部HTTP连接管理器使用ManagedHttpClientConnection实例作为管理连接状态并控制I / O操作执行的真实连接的代理。如果托管连接已被释放或被其使用方显式关闭,则基础连接会从其代理断开并返回给管理器,即使服务使用方仍然拥有对代理实例的引用,该连接也将无法执行任何I / O操作或有意或无意地更改实际连接的状态。” (HttpClent Tutorial)正如@oleg所指出的那样,跟踪连接的正确方法是使用logger。
最佳答案
首先,您需要确保正在使用的远程服务器支持保持活动连接。只需简单地检查远程服务器是否在每个响应中都返回标头Connection: Keep-Alive
或Connection: Closed
。对于Close
情况there is nothing,您可以这样做。您可以使用this online tool进行此类检查。
接下来,您需要实现this manual的#2.6段中定义的ConnectionKeepAliveStrategy
。请注意,您可以使用现有的DefaultConnectionKeepAliveStrategy
since HttpClient version 4.0,这样您的HttpClient
的结构将如下所示:
HttpClient client = HttpClients.custom()
.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
.build();
如果服务器支持的话,这将确保您的
HttpClient
实例将通过保持活动机制重用相同的连接。关于java - 如何使用Apache HttpClient获得持久的HttpConnection?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46053067/