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

版權聲明:本文爲博主原創文章,支持轉載,但轉載時請務必在明顯位置,給出原文作者名字(左瀟龍)及原文連接,否則,作者將保留追究法律責任的權利。 https://blog.csdn.net/zuoxiaolong8810/article/details/65441709

--------------------- 
作者:左瀟龍 
來源:CSDN 
原文:https://blog.csdn.net/zuoxiaolong8810/article/details/65441709 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

 

引言
  

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

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

  

以前的誤解
  

  很久之前LZ就聽說過長連接的說法,而且還知道HTTP1.0協議不支持長連接,從HTTP1.1協議以後,連接默認都是長連接。但LZ終究覺得對於長連接一直懵懵懂懂的,有種抓不到關鍵點的感覺。

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

  回到正題,既然說是誤解,那麼LZ的誤解到底是什麼?

  那就是LZ一直認爲,HTTP連接分爲長連接和短連接,而我們現在常用的都是HTTP1.1,因此我們用的都是長連接。

  這句話其實只對了一半,我們現如今的HTTP協議,大部分都是1.1的,因此我們平時用的基本上都是長連接。但是前半句是不對的,HTTP協議根本沒有長短連接這一說,也正因爲誤解了這個,導致LZ對於長連接一直不明不白,始終不得其要領,具體下面一段會說到。

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

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

  其實知道了以後,會覺得這很好理解。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感覺對於它們的理解又進了一步,這就是寫博客的好處吧。

  寫了這麼多,最後給自己打個小廣告(莫要拍磚,-_-),LZ每週都會在直播網站做直播,地址在博客左側,如果想要了解直播的時間,可以加LZ的交流羣,羣號同樣在博客左側。直播的內容主要是帶大家一起看源碼,看書,或者解答各種疑難雜症的問題,包括但不限於技術、職場、人生、情感等。

  最最後,如果你有任務調度框架的需求,請考慮一下niubi-job,多的這裏就不介紹了,請看LZ的博文。

  廣告時間結束!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章