HttpClient4.3教程 第二章 链接管理

HttpClient4.3教程 第二章 链接管理

2.1.持久链接

两个主机创建链接的过程是很复杂的一个过程,涉及到多个数据包的交换,而且也很耗时间。Http链接须要的三次握手开销很大,这一开销对于比较小的http消息来讲更大。可是若是咱们直接使用已经创建好的http链接,这样花费就比较小,吞吐率更大。
HTTP/1.1默认就支持Http链接复用。兼容HTTP/1.0的终端也能够经过声明来保持链接,实现链接复用。HTTP代理也能够在必定时间内保持链接不释放,方便后续向这个主机发送http请求。这种保持链接不释放的状况其实是创建的持久链接。HttpClient也支持持久链接。 java

2.2.HTTP链接路由

HttpClient既能够直接、又能够经过多个中转路由(hops)和目标服务器创建链接。HttpClient把路由分为三种plain(明文 ),tunneled(隧道)和layered(分层)。隧道链接中使用的多个中间代理被称做代理链。
客户端直接链接到目标主机或者只经过了一个中间代理,这种就是Plain路由。客户端经过第一个代理创建链接,经过代理链tunnelling,这种状况就是Tunneled路由。不经过中间代理的路由不可能时tunneled路由。客户端在一个已经存在的链接上进行协议分层,这样创建起来的路由就是layered路由。协议只能在隧道--->目标主机,或者直接链接(没有代理),这两种链路上进行分层。 浏览器

2.2.1.路由计算

RouteInfo接口包含了数据包发送到目标主机过程当中,通过的路由信息。HttpRoute类继承了RouteInfo接口,是RouteInfo的具体实现,这个类是不容许修改的。HttpTracker类也实现了RouteInfo接口,它是可变的,HttpClient会在内部使用这个类来探测到目标主机的剩余路由。HttpRouteDirector是个辅助类,能够帮助计算数据包的下一步路由信息。这个类也是在HttpClient内部使用的。
HttpRoutePlanner接口能够用来表示基于http上下文状况下,客户端到服务器的路由计算策略。HttpClient有两个HttpRoutePlanner的实现类。SystemDefaultRoutePlanner这个类基于java.net.ProxySelector,它默认使用jvm的代理配置信息,这个配置信息通常来自系统配置或者浏览器配置。DefaultProxyRoutePlanner这个类既不使用java自己的配置,也不使用系统或者浏览器的配置。它一般经过默认代理来计算路由信息。 安全

2.2.2. 安全的Http链接

为了防止经过Http消息传递的信息不被未受权的第三方获取、截获,Http可使用SSL/TLS协议来保证http传输安全,这个协议是当前使用最广的。固然也可使用其余的加密技术。可是一般状况下,Http信息会在加密的SSL/TLS链接上进行传输。 服务器

2.3. HTTP链接管理器

2.3.1. 管理链接和链接管理器

Http链接是复杂,有状态的,线程不安全的对象,因此它必须被妥善管理。一个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("www.yeetrack.com", 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);    }

若是要终止链接,能够调用ConnectionRequestcancel()方法。这个方法会解锁被ConnectionRequestget()方法阻塞的线程。 jvm

2.3.2.简单链接管理器

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

<

2.3.3.链接池管理器

相对BasicHttpClientConnectionManager来讲,PoolingHttpClientConnectionManager是个更复杂的类,它管理着链接池,能够同时为不少线程提供http链接请求。Connections are pooled on a per route basis.当请求一个新的链接时,若是链接池有有可用的持久链接,链接管理器就会使用其中的一个,而不是再建立一个新的链接。
PoolingHttpClientConnectionManager维护的链接数在每一个路由基础和总数上都有限制。默认,每一个路由基础上的链接不超过2个,总链接数不能超过20。在实际应用中,这个限制可能会过小了,尤为是当服务器也使用Http协议时。
下面的例子演示了若是调整链接池的参数: spa

继续阅读→

相关文章
相关标签/搜索