1. 管理连接和连接管理器
一个Http连接在同一时间只能被一个线程访问。HttpClient使用一个叫做Http连接管理器的特殊实体类来管理Http连接,这个实体类要实现HttpClientConnectionManager
接口。Http连接管理器在新建http连接时,作为工厂类;管理持久http连接的生命周期;同步持久连接(确保线程安全,即一个http连接同一时间只能被一个线程访问)。Http连接管理器和ManagedHttpClientConnection
的实例类一起发挥作用,ManagedHttpClientConnection
实体类可以看做http连接的一个代理服务器,管理着I/O操作。如果一个Http连接被释放或者被它的消费者明确表示要关闭,那么底层的连接就会和它的代理进行分离,并且该连接会被交还给连接管理器。这是,即使服务消费者仍然持有代理的引用,它也不能再执行I/O操作,或者更改Http连接的状态。
下面的代码展示了如何从连接管理器中取得一个http连接:
- HttpClientContext context = HttpClientContext.create();
- HttpClientConnectionManager connMrg = new BasicHttpClientConnectionManager();
- HttpRoute route = new HttpRoute(new HttpHost("localhost", 80));
- // 获取新的连接. 这里可能耗费很多时间
- ConnectionRequest connRequest = connMrg.requestConnection(route, null);
- // 10秒超时
- HttpClientConnection conn = connRequest.get(10, TimeUnit.SECONDS);
- try {
- // 如果创建连接失败
- if (!conn.isOpen()) {
- // establish connection based on its route info
- connMrg.connect(conn, route, 1000, context);
- // and mark it as route complete
- connMrg.routeComplete(conn, route, context);
- }
- // 进行自己的操作.
- } finally {
- connMrg.releaseConnection(conn, null, 1, TimeUnit.MINUTES);
- }
如果要终止连接,可以调用ConnectionRequest
的cancel()
方法。这个方法会解锁被ConnectionRequest
类get()
方法阻塞的线程。
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();
- // Increase max total connection to 200
- cm.setMaxTotal(200);
- // Increase default max connection per route to 20
- cm.setDefaultMaxPerRoute(20);
- // Increase max connections for localhost:80 to 50
- HttpHost localhost = new HttpHost("locahost", 80);
- cm.setMaxPerRoute(new HttpRoute(localhost), 50);
- CloseableHttpClient httpClient = HttpClients.custom()
- .setConnectionManager(cm)
- .build();
4.关闭连接管理器
当一个HttpClient的实例不在使用,或者已经脱离它的作用范围,我们需要关掉它的连接管理器,来关闭掉所有的连接,释放掉这些连接占用的系统资源。
- CloseableHttpClient httpClient = <...>
- httpClient.close();