一、背景
HTTP協(xié)議是無狀態(tài)的協(xié)議,即每一次請求都是互相獨立的。因此它的最初實現(xiàn)是,每一個http請求都會打開一個tcp socket連接,當交互完畢后會關(guān)閉這個連接。
HTTP協(xié)議是全雙工的協(xié)議,所以建立連接與斷開連接是要經(jīng)過三次握手與四次揮手的。顯然在這種設(shè)計中,每次發(fā)送Http請求都會消耗很多的額外資源,即連接的建立與銷毀。
于是,HTTP協(xié)議的也進行了發(fā)展,通過持久連接的方法來進行socket連接復(fù)用。
從圖中可以看到:
持久連接的實現(xiàn)有兩種:HTTP/1.0+的keep-alive與HTTP/1.1的持久連接。
二、HTTP/1.0+的Keep-Alive
從1996年開始,很多HTTP/1.0瀏覽器與服務(wù)器都對協(xié)議進行了擴展,那就是“keep-alive”擴展協(xié)議。
注意,這個擴展協(xié)議是作為1.0的補充的“實驗型持久連接”出現(xiàn)的。keep-alive已經(jīng)不再使用了,最新的HTTP/1.1規(guī)范中也沒有對它進行說明,只是很多應(yīng)用延續(xù)了下來。
使用HTTP/1.0的客戶端在首部中加上"Connection:Keep-Alive",請求服務(wù)端將一條連接保持在打開狀態(tài)。服務(wù)端如果愿意將這條連接保持在打開狀態(tài),就會在響應(yīng)中包含同樣的首部。如果響應(yīng)中沒有包含"Connection:Keep-Alive"首部,則客戶端會認為服務(wù)端不支持keep-alive,會在發(fā)送完響應(yīng)報文之后關(guān)閉掉當前連接。
通過keep-alive補充協(xié)議,客戶端與服務(wù)器之間完成了持久連接,然而仍然存在著一些問題:
三、HTTP/1.1的持久連接
HTTP/1.1采取持久連接的方式替代了Keep-Alive。
HTTP/1.1的連接默認情況下都是持久連接。如果要顯式關(guān)閉,需要在報文中加上Connection:Close首部。即在HTTP/1.1中,所有的連接都進行了復(fù)用。
然而如同Keep-Alive一樣,空閑的持久連接也可以隨時被客戶端與服務(wù)端關(guān)閉。不發(fā)送Connection:Close不意味著服務(wù)器承諾連接永遠保持打開。
四、HttpClient如何生成持久連接
HttpClien中使用了連接池來管理持有連接,同一條TCP鏈路上,連接是可以復(fù)用的。HttpClient通過連接池的方式進行連接持久化。
其實“池”技術(shù)是一種通用的設(shè)計,其設(shè)計思想并不復(fù)雜:
所有的連接池都是這個思路,不過我們看HttpClient源碼主要關(guān)注兩點:
4.1 HttpClient連接池的實現(xiàn)
HttpClient關(guān)于持久連接的處理在下面的代碼中可以集中體現(xiàn),下面從MainClientExec摘取了和連接池相關(guān)的部分,去掉了其他部分:
public class MainClientExec implements ClientExecChain { @Override public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpClientContext context, final HttpExecutionAware execAware) throws IOException, HttpException { //從連接管理器HttpClientConnectionManager中獲取一個連接請求ConnectionRequest final ConnectionRequest connRequest = connManager.requestConnection(route, userToken);final HttpClientConnection managedConn; final int timeout = config.getConnectionRequestTimeout(); //從連接請求ConnectionRequest中獲取一個被管理的連接HttpClientConnection managedConn = connRequest.get(timeout > 0 ? timeout : 0, TimeUnit.MILLISECONDS); //將連接管理器HttpClientConnectionManager與被管理的連接HttpClientConnection交給一個ConnectionHolder持有 final ConnectionHolder connHolder = new ConnectionHolder(this.log, this.connManager, managedConn); try { HttpResponse response; if (!managedConn.isOpen()) { //如果當前被管理的連接不是出于打開狀態(tài),需要重新建立連接 establishRoute(proxyAuthState, managedConn, route, request, context); } //通過連接HttpClientConnection發(fā)送請求 response = requestExecutor.execute(request, managedConn, context); //通過連接重用策略判斷是否連接可重用 if (reuseStrategy.keepAlive(response, context)) { //獲得連接有效期 final long duration = keepAliveStrategy.getKeepAliveDuration(response, context); //設(shè)置連接有效期 connHolder.setValidFor(duration, TimeUnit.MILLISECONDS); //將當前連接標記為可重用狀態(tài) connHolder.markReusable(); } else { connHolder.markNonReusable(); } } final HttpEntity entity = response.getEntity(); if (entity == null || !entity.isStreaming()) { //將當前連接釋放到池中,供下次調(diào)用 connHolder.releaseConnection(); return new HttpResponseProxy(response, null); } else { return new HttpResponseProxy(response, connHolder); } }
當前名稱:關(guān)于Http持久連接和HttpClient連接池的深入理解-創(chuàng)新互聯(lián)
標題網(wǎng)址:http://aaarwkj.com/article6/dopgig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、微信小程序、網(wǎng)站營銷、云服務(wù)器、軟件開發(fā)、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容