关于HttpClient中连接池是如何在HttpCloseableHttpResponse的close()执行后没有销毁HttpClient的

根据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,而是将连接放入了一个链表供后面使用。

以上。

你可能感兴趣的:(HttpClient)