Httpclient4.5详解之源码解析和使用二: 连接池内连接的创建 借出 归还

 

Httpclient4.5详解之源码解析和使用一: 关键执行流程源码解读

承接上文,本文我们查看httpcommons连接池的源码来分析一下连接池将连接缓存起来然后借出的归还的,其中建立的socket连接是如何关闭的,现在我们就通过源码来一看究竟。

创建和借出

上文源码分析流程提到,具体流程会执行到InternalHttpClient#doExecute和execChain#execute(其调用链最后一站为MainClientExec), MainClientExec#execute方法上文我们已经分析过他通过连接发送请求的代码,但是连接如何获取的我们还没有分析,现在再次进入到他的代码中查看。

 final ConnectionRequest connRequest = connManager.requestConnection(route, userToken);
        if (execAware != null) {
            if (execAware.isAborted()) {
                connRequest.cancel();
                throw new RequestAbortedException("Request aborted");
            } else {
                execAware.setCancellable(connRequest);
            }
        }

        final RequestConfig config = context.getRequestConfig();

        final HttpClientConnection managedConn;
        try {
            final int timeout = config.getConnectionRequestTimeout();
            managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS);
        } catch(final InterruptedException interrupted) {
            Thread.currentThread().interrupt();
            throw new RequestAbortedException("Request aborted", interrupted);
        } catch(final ExecutionException ex) {
            Throwable cause = ex.getCause();
            if (cause == null) {
                cause = ex;
            }
            throw new RequestAbortedException("Request execution failed", cause);
        }

 

其中第1行调用PoolingHttpClientConnectionManager#requestConnection返回一个ConnectionRequest,进入其方法内部查看

 public ConnectionRequest requestConnection(
            final HttpRoute route,
            final Object state) {
        Args.notNull(route, "HTTP route");
        if (this.log.isDebugEnabled()) {
            this.log.debug("Connection request: " + format(route, state) + formatStats(route));
        }
        final Future<CPoolEntry> future = this.pool.lease(route, state, null);
        return new ConnectionRequest() {

            @Override
            public boolean cancel() {
                return future.cancel(true);
            }

            @Override
            public HttpClientConnection get(
                    final long timeout,
                    final TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException {
                final HttpClientConnection conn = leaseConnection(future, timeout, tunit);
                if (conn.isOpen()) {
                    final HttpHost host;
                    if (route.getProxyHost() != null) {
                        host = route.getProxyHost();
                    } else {
                        host = route.getTargetHost();
                    }
                    final SocketConfig socketConfig = resolveSocketConfig(host);
                    conn.setSocketTimeout(socketConfig.getSoTimeout());
                }
                return conn;
            }

        };

    }

其中返回了一个有一个get方法的ConnectionRequest匿名内部类,所以才会有上个代码片段的第16行代码 managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS); 其中get方法中有final HttpClientConnection conn = leaseConnection(future, timeout, tunit)这段代码就是通过future这个参数获取connection的,在leaseConnection方法中通过entry = future.get(timeout, tunit)获取到已经包装好的连接对象CPoolEntry,所以现在重点就到了这个future身上,而这个future获取是在第8行。进入到Cpool的父类AbstractConnPool#lease具体看他的get方法

public E get(final long timeout, final TimeUnit tunit) throws InterruptedException, ExecutionException, TimeoutException {
                final E entry = entr
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值