HttpClient之连接池

Http

Http协议是无状态的协议,每一次请求都是相互独立的,因此,最开始的设计是,每个htt请求都会打开一个 tcp socket 连接,当交互完毕后关闭这个连接。HTTP协议是全双工协议,所以建立连接与断开连接是要经过三次握手与四次挥手,显然,在这种设计 中,每次发送HTTP请求都会消耗额外资源时间,即连接的建立与销毁。
所以,持久连接的方式进行socket连接复用,是比较好的方式。
在串行连接中,每次交互都要打开关闭连接
在持久连接中,第一次交互打开连接,交互结束后连接并不关闭,复用给下一次交互,直到全部交互完毕,关闭连接,这样就省去了每次建立连接的过程。

Http连接池

1、降低延迟:如果不采用连接池,每次连接发起Http请求的时候都会重新建立TCP连接(经历3次握手),用完就会关闭连接(4次挥手),如果采用连接池则减少了这部分时间损耗,别小看这几次握手,据说,基本上3倍的时间延迟

2、支持更大的并发:如果不采用连接池,每次连接都会打开一个端口,在大并发的情况下系统的端口资源很快就会被用完,导致无法建立新的连接(量变产生质变)

遇到的问题:有大量的TIME_WAIT,一边关闭连接,一边又请求打开连接,之前的没有关闭完成,没有释放完,端口被用完,没有可用端口,死循环,服务被压死。
出现:Cannot assign requested address
由于客户端频繁的连服务器,由于每次连接都在很短的时间内结束,导致很多的TIME_WAIT,以至于用光了可用的端 口号,所以新的连接没办法绑定端口,即“Cannot assign requested address”。是客户端的问题不是服务器端的问题。通过netstat,的确看到很多TIME_WAIT状态的连接。
client端频繁建立连接,而端口释放较慢,导致建立新连接时无可用端口。

HTTP连接池的设置

每个线程持有一个连接,并复用。

private CloseableHttpClient httpClient = HttpClients.custom().setMaxConnTotal(30).setMaxConnPerRoute(30).build();
 public  List<NumData> getHttpData(String an) throws Exception{
        List<NumData> listJsonData = new ArrayList<>();
        String url = "地址"+an;//url访问地址
        HttpGet httpGet = new HttpGet(url);

        String result = "";
        JSONArray jsonArray = null;
        CloseableHttpResponse response;
        HttpEntity httpEntity = null;
        try {
            response = httpClient.execute(httpGet);
            httpEntity = response.getEntity();
            if (httpEntity != null) {
                result = EntityUtils.toString(httpEntity, "utf-8");
            }
            try {
                jsonArray = JSONArray.fromObject(result);
            } catch (Exception e) {
                return null;
            }
            for(int i=0; i<jsonArray.size(); i++){
                NumData numData = new NumData();
                JSONObject obj = (JSONObject) jsonArray.get(i);
                Iterator it = obj.keys();
                while (it.hasNext()) {
                    String key = it.next().toString();
                    if("an".equals(key)){
                        numData.setAn(obj.getString(key));
                        numData.setTARGET_SORT(i+1);
                        break;
                    }
                }
                listJsonData.add(numData);

            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (httpEntity != null) {
                EntityUtils.consume(httpEntity);
            }
        }
        return listJsonData;
    }
    public static void staticClose() throws IOException {
        httpUtils.close();
    }

setMaxConnTotal(30):设置最大连接数
setMaxConnPerRoute(30):设置每个路由默认连接数

EntityUtils对象是org.apache.http.util下的一个工具类,用官方的解释是为HttpEntity对象提供的静态帮助类,其常用的几个方法如下:

consume()方法;

consumeQuietly(HttpEntity)方法

toByteArray(final HttpEntity entity)方法

最主要的就是consume()这个方法,其功能就是关闭HttpEntity的流
对于实体的资源使用完之后要适当的回收资源,特别是对于流实体

猜你喜欢

转载自blog.csdn.net/Growing_way/article/details/82108174