HTTP協議中的短輪詢、長輪詢、長鏈接和短鏈接

序言

最近剛到公司不到一個月,正處於熟悉項目和源碼的階段,所以最近常常會看一些源碼。在研究一個項目的時候,源碼裏面用到了HTTP的長輪詢。因爲以前沒太接觸過,所以LZ便趁着這個機會,好好了解了一下HTTP的長長短短。html

瞭解的方式主要都是LZ在網絡上獲取的,這裏只是談一下LZ對於這四種叫法最直觀的理解。若是你以前不懂的話,能夠幫你普及一下,若是你以前就懂得話,能夠互相對照一下。數據庫

之前的誤解

好久以前LZ就據說過長鏈接的說法,並且還知道HTTP1.0協議不支持長鏈接,從HTTP1.1協議之後,鏈接默認都是長鏈接。但LZ終究以爲對於長鏈接一直懵懵懂懂的,有種抓不到關鍵點的感受。編程

今天LZ經過一番研究,終於明白了這其中的奧祕。而以前,LZ也看過長鏈接相關的內容,但一直都是雲裏霧裏的。此次之因此能在這麼短的時間裏搞清楚,和LZ本身技術的沉澱密不可分。所以,這裏LZ藉着這個機會,再次強調一下,千萬不要試圖去研究你研究了好久都整不明白的東西,或許是你的層次不到,也或許是你從未在實際的應用場景接觸過,這種狀況下你去研究,只會事倍功半,徒勞一番罷了。服務器

回到正題,既然說是誤解,那麼LZ的誤解究竟是什麼?網絡

那就是LZ一直認爲,HTTP鏈接分爲長鏈接和短鏈接,而咱們如今經常使用的都是HTTP1.1,所以咱們用的都是長鏈接。spa

這句話其實只對了一半,咱們現現在的HTTP協議,大部分都是1.1的,所以咱們平時用的基本上都是長鏈接。可是前半句是不對的,HTTP協議根本沒有長短鏈接這一說,也正由於誤解了這個,致使LZ對於長鏈接一直不明不白,始終不得其要領,具體下面一段會說到。線程

網絡上不少文章都是誤人子弟,根本沒有說明白這個概念。這裏LZ要強調一下,HTTP協議是基於請求/響應模式的,所以只要服務端給了響應,本次HTTP鏈接就結束了,或者更準確的說,是本次HTTP請求就結束了,根本沒有長鏈接這一說。那麼天然也就沒有短鏈接這一說了。htm

之因此網絡上說HTTP分爲長鏈接和短鏈接,其實本質上是說的TCP鏈接。TCP鏈接是一個雙向的通道,它是能夠保持一段時間不關閉的,所以TCP鏈接纔有真正的長鏈接和短鏈接這一說blog

其實知道了之後,會以爲這很好理解。HTTP協議說究竟是應用層的協議,而TCP纔是真正的傳輸層協議,只有負責傳輸的這一層才須要創建鏈接。圖片

一個形象的例子就是,拿你在網上購物來講,HTTP協議是指的那個快遞單,你寄件的時候填的單子就像是發了一個HTTP請求,等貨物運到地方了,快遞員會根據你發的請求把貨物送給相應的收貨人。而TCP協議就是中間運貨的那個大貨車,也多是火車或者飛機,但無論是什麼,它是負責運輸的,所以必需要有路,無論是地上仍是天上。那麼這個路就是所謂的TCP鏈接,也就是一個雙向的數據通道。

所以,LZ如今甚至以爲,「HTTP鏈接」這個詞就不該該出現,它只是一個應用層的協議,根本就沒有所謂的鏈接這一說,就像FTP也是應用層的協議,可是你有據說過FTP鏈接嗎?(恩,好像是聽過,-_-,但你如今知道了,其實所謂的FTP鏈接,嚴格來講,依舊是TCP鏈接)

實際上,說HTTP請求和HTTP響應會更準確一些,而HTTP請求和HTTP響應,都是經過TCP鏈接這個通道來回傳輸的。

無論怎麼說,必定要務必記住,長鏈接是指的TCP鏈接,而不是HTTP鏈接。

一個疑問

以前LZ一直對一件事有些模糊不清,首先是怎麼樣就算是把HTTP變成長鏈接了,是否是隻要設置Connection爲keep-alive就算是了?

若是是的話,那都說HTTP1.1默認是長鏈接,而觀察咱們平時開發的Web應用的HTTP頭部,Connection也確實是keep-alive,那就是說咱們大部分都是用的長鏈接,可是長鏈接不是通常用於交互比較頻繁的應用嗎?像咱們這種普通的Web應用,好比博客園這種,或者個人我的博客這種,長鏈接有什麼用?

若是有用那用處究竟是什麼,咱們又不是客戶端與服務器交互頻繁的那種應用(畢竟你打開網頁確定要半天才打開另一個吧),若是沒用的話,那到底應不該該把Connection爲keep-alive這個header值給改掉,從而改爲短鏈接?

這個疑問,在LZ明白了長鏈接實際上是指的TCP鏈接以後,基本上就明白了。而這個疑問,也正是LZ在「之前的誤解」那一段所提到的,那個由於誤解致使LZ一直搞不明白的問題。

爲何解決了上面那個誤解以後,前面所說的這些疑問LZ都明白了?

由於長鏈接意味着鏈接會被複用,畢竟一直保持着鏈接不就是爲了重複使用嘛。但若是長鏈接是指的HTTP的話,那就是說HTTP鏈接能夠被重複利用,這個話聽起來就感受很彆扭。之因此以爲彆扭,其實就是LZ的一種直覺,沒什麼理論依據。而這種彆扭的根源就在於,以前一直沒有融會貫通的感受,因此總感受缺乏點什麼。不過這點疑惑,並無影響LZ的工做,所以也就沒深究過。

但如今好了,明白了長鏈接其實是指的TCP鏈接,LZ瞬間本身就想明白了上面的那些問題。

第一個問題是,是否是隻要設置Connection爲keep-alive就算是長鏈接了?

固然是的,但要服務器和客戶端都設置。

第二個問題是,咱們平時用的是否是長鏈接?

這個也毫無疑問,固然是的。(如今用的基本上都是HTTP1.1協議,你觀察一下就會發現,基本上Connection都是keep-alive。並且HTTP協議文檔上也提到了,HTTP1.1默認是長鏈接,也就是默認Connection的值就是keep-alive)

第三個問題,也是LZ以前最想不明白的問題,那就是咱們這種普通的Web應用(好比博客園,個人我的博客這種)用長鏈接有啥好處?需不須要關掉長鏈接而使用短鏈接?

這個問題LZ如今終於明白了,問題的答案是好處仍是有的。

好處是什麼?

首先,剛纔已經說了,長鏈接是爲了複用,這個在以前LZ就明白。那既然長鏈接是指的TCP鏈接,也就是說複用的是TCP鏈接。那這就很好解釋了,也就是說,長鏈接狀況下,多個HTTP請求能夠複用同一個TCP鏈接,這就節省了不少TCP鏈接創建和斷開的消耗。

好比你請求了博客園的一個網頁,這個網頁裏確定還包含了CSS、JS等等一系列資源,若是你是短鏈接(也就是每次都要從新創建TCP鏈接)的話,那你每打開一個網頁,基本要創建幾個甚至幾十個TCP鏈接,這浪費了多少資源就不用LZ去說了吧。

但若是是長鏈接的話,那麼這麼屢次HTTP請求(這些請求包括請求網頁內容,CSS文件,JS文件,圖片等等),其實使用的都是一個TCP鏈接,很顯然是能夠節省不少消耗的。

這樣一解釋,就很明白了,不知道你們看了這些解釋感受如何,反正LZ在本身想明白之後,有種豁然開朗的感受。

另外,最後關於長鏈接還要多提一句,那就是,長鏈接並非永久鏈接的。若是一段時間內(具體的時間長短,是能夠在header當中進行設置的,也就是所謂的超時時間),這個鏈接沒有HTTP請求發出的話,那麼這個長鏈接就會被斷掉。

這一點其實很容易理解,不然的話,TCP鏈接將會愈來愈多,直到把服務器的TCP鏈接數量撐爆到上限爲止。如今想一想,對於服務器來講,服務器裏的這些個長鏈接其實頗有數據庫鏈接池的味道,你們都是爲了節省鏈接重複利用嘛,對不對?

長輪詢和短輪詢

前面基本上LZ已經把長短鏈接說的差很少了,接下來講說長短輪詢,今天也正是爲了研究長短輪詢,LZ才順便研究了下長短鏈接這回事。

短輪詢相信你們都不難理解,好比你如今要作一個電商中商品詳情的頁面,這個詳情界面中有一個字段是庫存量(相信這個你們都不陌生,隨便打開淘寶或者京東都能找到這種頁面)。而這個庫存量須要實時的變化,保持和服務器裏實際的庫存一致。

這個時候,你會怎麼作?

最簡單的一種方式,就是你用JS寫個死循環,不停的去請求服務器中的庫存量是多少,而後刷新到這個頁面當中,這其實就是所謂的短輪詢。

這種方式有明顯的壞處,那就是你很浪費服務器和客戶端的資源。客戶端還好點,如今PC機配置高了,你不停的請求還不至於把用戶的電腦整死,可是服務器就很蛋疼了。若是有1000我的停留在某個商品詳情頁面,那就是說會有1000個客戶端不停的去請求服務器獲取庫存量,這顯然是不合理的。

那怎麼辦呢?

長輪詢這個時候就出現了,其實長輪詢和短輪詢最大的區別是,短輪詢去服務端查詢的時候,無論庫存量有沒有變化,服務器就當即返回結果了。而長輪詢則不是,在長輪詢中,服務器若是檢測到庫存量沒有變化的話,將會把當前請求掛起一段時間(這個時間也叫做超時時間,通常是幾十秒)。在這個時間裏,服務器會去檢測庫存量有沒有變化,檢測到變化就當即返回,不然就一直等到超時爲止。

而對於客戶端來講,無論是長輪詢仍是短輪詢,客戶端的動做都是同樣的,就是不停的去請求,不一樣的是服務端,短輪詢狀況下服務端每次請求無論有沒有變化都會當即返回結果,而長輪詢狀況下,若是有變化纔會當即返回結果,而沒有變化的話,則不會再當即給客戶端返回結果,直到超時爲止。 

這樣一來,客戶端的請求次數將會大量減小(這也就意味着節省了網絡流量,畢竟每次發請求,都會佔用客戶端的上傳流量和服務端的下載流量),並且也解決了服務端一直疲於接受請求的窘境。

可是長輪詢也是有壞處的,由於把請求掛起一樣會致使資源的浪費,假設仍是1000我的停留在某個商品詳情頁面,那就頗有可能服務器這邊掛着1000個線程,在不停檢測庫存量,這依然是有問題的。

所以,從這裏能夠看出,無論是長輪詢仍是短輪詢,都不太適用於客戶端數量太多的狀況,由於每一個服務器所能承載的TCP鏈接數是有上限的,這種輪詢很容易把鏈接數頂滿。之因此舉這個例子,只是由於你們確定都會網購,因此這個例子比較通俗一點。

哪怕輪詢解決不了獲取庫存這個問題,但只要你們明白了長短輪詢的區別,這就足夠了。實際上,據LZ本身平日裏購物的觀察,那個庫存量應該是不會變的,這個例子純屬LZ我的的意淫,-_-。、

長輪詢和長短鏈接的區別

這裏簡單說一下它們的區別,LZ這裏只說最根本的區別。

第一個區別是決定的方式,一個TCP鏈接是否爲長鏈接,是經過設置HTTP的Connection Header來決定的,並且是須要兩邊都設置纔有效。而一種輪詢方式是否爲長輪詢,是根據服務端的處理方式來決定的,與客戶端沒有關係。

第二個區別就是實現的方式,鏈接的長短是經過協議來規定和實現的。而輪詢的長短,是服務器經過編程的方式手動掛起請求來實現的。

結語

好了,本文就到此爲止吧。LZ寫這篇文章,主要也是爲了不本身遺忘。說實話,寫到最後了,LZ感受對於它們的理解又進了一步,這就是寫博客的好處吧。

 

做者:左瀟龍

原文地址:http://www.cnblogs.com/zuoxiaolong/p/life49.html

相關文章
相關標籤/搜索