HttpClinet连接池远程调用接口 无法获取连接资源

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool

问题描述:无法从httpClient连接池获取有效连接对象

import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
@Resouce
CloseableHttpClient httpClient;
/**
*调用远程连接的时候,即是从httpClient 池中获取一个链接对象
*当调用结束,应该关闭连接,不然会占用资源,导致最后无可用的连接对象
**/
CloseableHttpResponse response = this.httpClient.execute(HttpGet);
/**
*关闭连接对象(即归还连接资源),以下两个方法都为关闭连接资源
**/
EntityUtils.toString(response.getEntity(), "UTF-8");//返回响应体的数据并关闭资源
EntityUtils.consumeQuietly(response.getEntity());//只是关闭连接资源

源码解析:

EntityUtils.toString(response.getEntity(), "UTF-8");
//源码展示
 private static String toString(HttpEntity entity, ContentType contentType) throws IOException {
        InputStream instream = entity.getContent();
        if (instream == null) {
            return null;
        } else {
            try {
                Args.check(entity.getContentLength() <= 2147483647L, "HTTP entity too large to be buffered in memory");
                int capacity = (int)entity.getContentLength();
                if (capacity < 0) {
                    capacity = 4096;
                }

                Charset charset = null;
                if (contentType != null) {
                    charset = contentType.getCharset();
                    if (charset == null) {
                        ContentType defaultContentType = ContentType.getByMimeType(contentType.getMimeType());
                        charset = defaultContentType != null ? defaultContentType.getCharset() : null;
                    }
                }

                if (charset == null) {
                    charset = HTTP.DEF_CONTENT_CHARSET;
                }

                Reader reader = new InputStreamReader(instream, charset);
                CharArrayBuffer buffer = new CharArrayBuffer(capacity);
                char[] tmp = new char[1024];

                int l;
                while((l = reader.read(tmp)) != -1) {
                    buffer.append(tmp, 0, l);
                }

                String var9 = buffer.toString();
                return var9;
            } finally {
            /**
            *最终关闭读取response流,即关闭连接资源
            **/
                instream.close();
            }
        }
    }
EntityUtils.consumeQuietly(response.getEntity());
/**
*源码解析
**/

public static void consume(HttpEntity entity) throws IOException {
        if (entity != null) {
            if (entity.isStreaming()) {
                InputStream instream = entity.getContent();
                if (instream != null) {
                /**
                *最终都是把读取response响应体的读取流关闭,及关闭连接资源
                **/
                    instream.close();
                }
            }

        }
    }

结论:

@Resouce
CloseableHttpClient httpClient;

httpClient 对象即是一个http连接池,从连接池中获取连接对象,即是获取读取流对象
一旦调用完远程接口,必须把 连接关闭(即关闭读取流)

所以httpClient调用远程接口的方法里都少不了最终的操作—关闭连接:

EntityUtils.consumeQuietly(response.getEntity());

没有关闭导致的问题如下:
一旦调用远程接口出错,响应码是500,或者其他错误码,连接无法释放,便一直占用着这个链接资源,而且回收机制并不会回收connect对象,因为它是处于活跃状态的,一直占用,当httpClient连接池资源耗尽,再想从连接池中获取连接connect对象时便会报一开始的错误

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值