伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

HTTP连接池

来源:本站原创 浏览:104次 时间:2022-10-22


1.为什么要用Http连接池

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

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

2.简单连接管理器

BasicHttpClientConnectionManager是个简单的连接管理器,它一次只能管理一个连接。尽管这个类是线程安全的,它在同一时间也只能被一个线程使用。BasicHttpClientConnectionManager会尽量重用旧的连接来发送后续的请求,并且使用相同的路由。如果后续请求的路由和旧连接中的路由不匹配,BasicHttpClientConnectionManager就会关闭当前连接,使用请求中的路由重新建立连接。如果当前的连接正在被占用,会抛出java.lang.IllegalStateException异常。

3.连接池管理器

相对BasicHttpClientConnectionManager来说,PoolingHttpClientConnectionManager是个更复杂的类,它管理着连接池,可以同时为很多线程提供http连接请求。Connections are pooled on a per route basis.当请求一个新的连接时,如果连接池有有可用的持久连接,连接管理器就会使用其中的一个,而不是再创建一个新的连接。

PoolingHttpClientConnectionManager维护的连接数在每个路由基础和总数上都有限制。默认,每个路由基础上的连接不超过2个,总连接数不能超过20。在实际应用中,这个限制可能会太小了,尤其是当服务器也使用Http协议时。

下面的例子演示了如果调整连接池的参数:

    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();    // 将最大连接数增加到200    cm.setMaxTotal(200);    // 将每个路由基础的连接增加到20    cm.setDefaultMaxPerRoute(20);    //将目标主机的最大连接数增加到50    HttpHost localhost = new HttpHost("www.yeetrack.com", 80);    cm.setMaxPerRoute(new HttpRoute(localhost), 50);    CloseableHttpClient httpClient = HttpClients.custom()            .setConnectionManager(cm)            .build();
4.关闭连接管理器

当一个HttpClient的实例不在使用,或者已经脱离它的作用范围,我们需要关掉它的连接管理器,来关闭掉所有的连接,释放掉这些连接占用的系统资源。

    CloseableHttpClient httpClient = <...>    httpClient.close();
5. 连接回收策略

经典阻塞I/O模型的一个主要缺点就是只有当组侧I/O时,socket才能对I/O事件做出反应。当连接被管理器收回后,这个连接仍然存活,但是却无法监控socket的状态,也无法对I/O事件做出反馈。如果连接被服务器端关闭了,客户端监测不到连接的状态变化(也就无法根据连接状态的变化,关闭本地的socket)。

HttpClient为了缓解这一问题造成的影响,会在使用某个连接前,监测这个连接是否已经过时,如果服务器端关闭了连接,那么连接就会失效。这种过时检查并不是100%有效,并且会给每个请求增加10到30毫秒额外开销。唯一一个可行的,且does not involve a one thread per socket model for idle connections的解决办法,是建立一个监控线程,来专门回收由于长时间不活动而被判定为失效的连接。这个监控线程可以周期性的调用ClientConnectionManager类的closeExpiredConnections()方法来关闭过期的连接,回收连接池中被关闭的连接。它也可以选择性的调用ClientConnectionManager类的closeIdleConnections()方法来关闭一段时间内不活动的连接。

    public static class IdleConnectionMonitorThread extends Thread {        private final HttpClientConnectionManager connMgr;        private volatile boolean shutdown;        public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {            super();            this.connMgr = connMgr;        }        @Override        public void run() {            try {                while (!shutdown) {                    synchronized (this) {                        wait(5000);                        // 关闭失效的连接                        connMgr.closeExpiredConnections();                        // 可选的, 关闭30秒内不活动的连接                        connMgr.closeIdleConnections(30, TimeUnit.SECONDS);                    }                }            } catch (InterruptedException ex) {                // terminate            }        }        public void shutdown() {            shutdown = true;            synchronized (this) {                notifyAll();            }        }    }
6. 连接存活策略

Http规范没有规定一个持久连接应该保持存活多久。有些Http服务器使用非标准的Keep-Alive头消息和客户端进行交互,服务器端会保持数秒时间内保持连接。HttpClient也会利用这个头消息。如果服务器返回的响应中没有包含Keep-Alive头消息,HttpClient会认为这个连接可以永远保持。然而,很多服务器都会在不通知客户端的情况下,关闭一定时间内不活动的连接,来节省服务器资源。在某些情况下默认的策略显得太乐观,我们可能需要自定义连接存活策略。

    ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {            // Honor 'keep-alive' header            HeaderElementIterator it = new BasicHeaderElementIterator(                    response.headerIterator(HTTP.CONN_KEEP_ALIVE));            while (it.hasNext()) {                HeaderElement he = it.nextElement();                String param = he.getName();                String value = he.getValue();                if (value != null && param.equalsIgnoreCase("timeout")) {                    try {                        return Long.parseLong(value) * 1000;                    } catch(NumberFormatException ignore) {                    }                }            }            HttpHost target = (HttpHost) context.getAttribute(                    HttpClientContext.HTTP_TARGET_HOST);            if ("www.naughty-server.com".equalsIgnoreCase(target.getHostName())) {                // Keep alive for 5 seconds only                return 5 * 1000;            } else {                // otherwise keep alive for 30 seconds                return 30 * 1000;            }        }    };    CloseableHttpClient client = HttpClients.custom()            .setKeepAliveStrategy(myStrategy)            .build();

7.原理及注意事项

连接池中连接都是在发起请求的时候建立,并且都是长连接

in.close();作用就是将用完的连接释放,下次请求可以复用,这里特别注意的是,如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭,并且不能被复用,这样就失去了采用连接池的意义。

连接池释放连接的时候,并不会直接对TCP连接的状态有任何改变,只是维护了两个Set,leased和avaliabled,leased代表被占用的连接集合,avaliabled代表可用的连接的集合,释放连接的时候仅仅是将连接从leased中remove掉了,并把连接放到avaliabled集合中


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net