直接說結論:
長連接:TCP連接一直不斷開的連接
keep-alive能實現長連接。
1.但是有時間限制,最多時間長一些而已 2.需要服務端也支持keep-alive,因為TCP連接的斷開是雙向的,不是客戶端說我要保持連接就行
keep-alive實現的長連接和websocket的長連接不同:
keep-alive是HTTP協議層面的長連接,不能主動推消息,主要是進行連接復用的
websocket是websocket協議的長連接,只要不斷開,連接一直都在,而且服務端可以主動推消息
keep-alive和websocket應用場景
- keep-alive用於需要發了HTTP請求后,需要連接復用的場景:
- 打開一個頁面時,該頁面鏈接了n個圖片或n個js腳本或n個css等,並且這些東西都在一台server上;
- 需要用戶頻繁的在網站中轉悠,這點點那點點;
- keep-alive不能用在短時間內高並發的場景
- websocket用於連接不多的場景或者需要服務端推送的場景,因為是長連接,所以服務器能提供的連接數是有限的。
HTTP長輪詢:服務器收到請求后如果有數據, 立刻響應請求; 如果沒有數據就會 hold 一段時間,這段時間內如果有數據立刻響應請求; 如果時間到了還沒有數據, 則響應 http 請求;瀏覽器受到 http 響應后立在發送一個同樣http 請求查詢是否有數據;
(長輪詢個人理解:“服務端hold住請求”如何實現?是不是有個死循環在一直監測,有數據變化就返回。)
HTTP短輪詢:服務器收到請求不管是否有數據都直接響應 http 請求; 瀏覽器受到 http 響應隔一段時間在發送同樣的http 請求查詢是否有數據;
長輪詢短輪詢使用場景:
- 長輪詢多用於web聊天場景,實時性高,還有一個web微信登錄掃碼的場景也是用的長輪詢,手機一掃二維碼,網頁就顯示用戶頭像
- 短輪詢多用於實時性不高的場景。(celery查詢狀態就是短輪詢,要注意結合keep-alive使用)
- 短輪詢多用於實時性不高的場景。(celery查詢狀態就是短輪詢,要注意結合keep-alive使用)
HTTP協議的核心: 先有請求,才有響應。有了請求,就要建TCP連接。所以造就了服務端沒辦法主動推消息,因為找不到發給誰。
在http早期,每個http請求都要求打開一個tpc socket連接,並且使用一次之后就斷開這個tcp連接。 使用keep-alive可以在一次TCP連接中可以持續發送多份數據而不會斷開連接。 Httpd守護進程,提供了keep-alive timeout時間設置參數。
這個keepalive_timout意味着:一個http請求產生的tcp連接在傳送完最后一個響應后,還需要hold住keepalive_timeout秒后,才關閉這個socket連接。
設置:Keep-Alive: timeout=5, max=100 // 第一次HTTP請求5秒后自動斷開TCP連接,5s內HTTP請求超過100次,斷開TCP連接。
keepalive由客戶端發HTTP請求(建立TCP連接)時進行設置
HTTP的keep-alive 跟 TCP的keep-alive是兩個不同的東西
HTTP的keep-alive說的是我這次請求的TCP連接要保持多長時間不關閉。
TCP的keep-alive是監測我TCP連接保持的這段時間內,雙方是不是通的,不通就關閉TCP連接。
設置了keep-alive(http請求頭)就是長連接(socket)了嗎?
長連接是什么? 長連接是socket建立后一直不關閉,叫長連接。
短連接是什么?短連接是socket建立,通訊一次后,關閉socket。
所以,長連接和短連接在於client和server采取的socket關閉策略。服務器是資源提供者,所以服務器的連接關閉策略就很重要了
所以,問題變成:
設置了keep-alive(http請求頭)服務端socket就不關閉了嗎?
顯然需要請求和服務器雙方都設置keep-alive才行。 可以在不同的服務器軟件中設定這個時間,nginx,或Apache的keep-alive時間
設置了keep-alive(http請求頭),高並發場景服務端設置keep-alive合適嗎?
如果同時有大量請求,服務端socket短時間得不到釋放,肯定崩潰
雙方都支持keep-alive了,用在哪些場景?
- 打開一個頁面時,該頁面鏈接了n個圖片或n個js腳本或n個css等,並且這些東西都在一台server上;
- 需要用戶頻繁的在網站中轉悠,這點點那點點;
keep-alive能實現長連接(有時間限制的長連接),但是這個連接除了拿來復用之外沒別的用處。和websocket的長連接有什么區別呢
這是協議層面的區別。http 協議規定了 http 連接是一個一來(request)一回(response)的過程。一個請求獲得一個響應后必須斷掉。而且只有先有請求才會有響應。拿 http1.1 keep-alive 來說,即使底層 tcp 連接沒有斷,服務端無緣無故給瀏覽器發一個 http 響應,瀏覽器是不收的,他找不到收的人啊,因為這個響應沒有對應的請求。你看 ajax 必須先發請求才會有一個 onsuccess 回調來響應這個請求。這個 onsuccess 的回調會在你 ajax 不發送的情況下被調用到嗎?
而 WebSocket 協議不同,他通過握手之后規定說你連接給我保持着,別斷咯。所以瀏覽器服務器在這種情況下可以相互的發送消息。瀏覽器端 new 一個 WebSocket 之后注冊 onmessage 回調,那么這個 onmessage 可以被反復調用,只要服務器端有消息過來。而不會說是 new 一個 WebSocket onmessage 只會被調用一次,下次還得再 new 一個 websocket。
上面說到 http 連接,tcp 連接,websockt 連接到底啥區別。其實這是新人最容易搞不懂的地方。接下來我就要胡謅了,為啥說胡謅,因為我只是看了個皮毛,然后按我自己的理解說下區別。網絡5層分層(自下而上):
物理層
數據鏈路層
網絡層
傳輸層
應用層
http,websocket都是應用層協議,他們規定的是數據怎么封裝,而他們傳輸的通道是下層提供的。就是說無論是 http 請求,還是 WebSocket 請求,他們用的連接都是傳輸層提供的,即 tcp 連接(傳輸層還有 udp 連接)。只是說 http1.0 協議規定,你一個請求獲得一個響應后,你要把連接關掉。所以你用 http 協議發送的請求是無法做到一直連着的(如果服務器一直不返回也可以保持相當一段時間,但是也會有超時而被斷掉)。而 WebSocket 協議規定說等握手完成后我們的連接不能斷哈。雖然 WebSocket 握手用的是 http 請求,但是請求頭和響應頭里面都有特殊字段,當瀏覽器或者服務端收到后會做相應的協議轉換。所以 http 請求被 hold 住不返回的長連接和 WebSocket 的連接是有本質區別的。