【发布时间】:2018-02-13 15:17:30
【问题描述】:
在我的测试应用程序中,我使用 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。
【问题讨论】:
标签: java apache-httpclient-4.x