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

繼續閱讀→

相關文章
相關標籤/搜索