根据Apache HttpClient 4.5.6讲解。
HttpClient使用如下方式创建HttpClient时,在build()中会默认给HttpClient设置一个连接池PoolingHttpClientConnectionManager
return HttpClientBuilder.create().build();
默认创建的HttpClient是默认保持连接的keepalive。
我们使用HttpClient请求第三方服务器时,如果请求的是同一个服务器的地址是可以提高访问效率的。这是由于HTTP协议的底层是TCP,TCP建立连接的时候需要三次握手。如果使用连接池并keeplive是true,那么就是一个长链接,在第一次握手成功后,后面的请求就都不需要握手了,直接请求数据,这样就加快了访问速度。但是,如果多次请求的不是同一个服务器,还是需要为每次请求握手建立连接。如果项目中有对某一个平台比如微信开放平台有频繁的调用,可以使用一个HttpClient去专门请求,这样只会进行一次握手。
我们一般使用HttpClient后都会关闭,比如:
CloseableHttpResponse response = this.execute(target, request, context);
....
finally {
response.close();
}
那有没有想过这样关闭会对我上面说的长链接有影响吗?
这样关闭是没有影响的,它还是在连接池中。close()最后会调用这个方法。
private void releaseConnection(boolean reusable) {
if (this.released.compareAndSet(false, true)) {
HttpClientConnection var2 = this.managedConn;
synchronized(this.managedConn) {
if (reusable) {
this.manager.releaseConnection(this.managedConn, this.state, this.validDuration, this.tunit);
} else {
try {
this.managedConn.close();
this.log.debug("Connection discarded");
} catch (IOException var9) {
if (this.log.isDebugEnabled()) {
this.log.debug(var9.getMessage(), var9);
}
} finally {
this.manager.releaseConnection(this.managedConn, (Object)null, 0L, TimeUnit.MILLISECONDS);
}
}
}
}
}
可以看到是通过reusable去判断的。这个在CloseableHttpResponse构造的时候就已经设定了。
if (reuseStrategy.keepAlive(response, context)) {
// Set the idle duration of this connection
final long duration = keepAliveStrategy.getKeepAliveDuration(response, context);
if (this.log.isDebugEnabled()) {
final String s;
if (duration > 0) {
s = "for " + duration + " " + TimeUnit.MILLISECONDS;
} else {
s = "indefinitely";
}
this.log.debug("Connection can be kept alive " + s);
}
connHolder.setValidFor(duration, TimeUnit.MILLISECONDS);
connHolder.markReusable();
}
public void markReusable() {
this.reusable = true;
}
看这个大概就可以看出,就是通过keepAlive去判断的。
回到前面的releaseConnection(),它没有去关闭socket,而是将连接放入了一个链表供后面使用。
以上。