IM通信技術(shù)快速入門:短輪詢、長輪詢、SSE、WebSocket
前言
? 哈啰,大家好,我是洛林,對Web端即時(shí)通訊技術(shù)熟悉的開發(fā)者來說,回顧整個(gè)網(wǎng)頁端IM的底層通信技術(shù)發(fā)展,從短輪詢、長輪詢,到后來的SSE以及WebSocket,我們使用的技術(shù)越來越先進(jìn),使用門檻也越來越低,給大家?guī)淼木W(wǎng)頁端體驗(yàn)也越來越好。
? 因此,我們很多時(shí)候沒有必要盲目追求新技術(shù),而是適合場景的技術(shù)才是最好的技術(shù),掌握WebSocket這些主流新技術(shù)固然重要,但了解短輪詢、長輪詢等所謂的“老技術(shù)”仍然大有裨益,這就是我分享這篇技術(shù)的原因。
即時(shí)通訊
? 對于IM/消息推送這類即時(shí)通訊系統(tǒng)而言,系統(tǒng)的關(guān)鍵就是“實(shí)時(shí)通信”能力。所謂實(shí)時(shí)通信有以下兩層含義:
1、客戶端可以主動向服務(wù)端發(fā)送信息。
2、當(dāng)服務(wù)端內(nèi)容發(fā)生變化時(shí),服務(wù)端可以實(shí)時(shí)通知客戶端。
常用技術(shù)
? 客戶端輪詢:傳統(tǒng)意義上的短輪詢(Short Polling)
? 服務(wù)器端輪詢:長輪詢(Long Polling)
? 單向服務(wù)器推送:Server-Sent Events(SSE)
? 全雙工通信:WebSocket
短輪詢(Short Polling)
實(shí)現(xiàn)原理
? 客戶端向服務(wù)器端發(fā)送一個(gè)請求,服務(wù)器返回?cái)?shù)據(jù),然后客戶端根據(jù)服務(wù)器端返回的數(shù)據(jù)進(jìn)行處理。
? 客戶端繼續(xù)向服務(wù)器端發(fā)送請求,繼續(xù)重復(fù)以上的步驟。(為了減小服務(wù)端壓力一般會采用定時(shí)輪詢的方式)
短輪詢通信過程
優(yōu)點(diǎn)
? 實(shí)現(xiàn)簡單,不需要額外開發(fā),僅需要定時(shí)發(fā)起請求,解析響應(yīng)即可。
缺點(diǎn)
? 不斷的發(fā)起請求和關(guān)閉請求,性能損耗以及對服務(wù)端的壓力較大,且HTTP請求本身本身比較耗費(fèi)資源。
? 輪詢間隔不好控制。如果實(shí)時(shí)性要求較高,短輪詢是明顯的短板,但如果設(shè)置太長,會導(dǎo)致消息延遲。
長輪詢(Long Polling)
實(shí)現(xiàn)原理
? 客戶端發(fā)送一個(gè)請求,服務(wù)器會hold住這個(gè)請求。
? 直到監(jiān)聽的內(nèi)容有改變,才會返回?cái)?shù)據(jù),斷開連接(或者在一定的時(shí)間內(nèi),請求還得不到返回,就會因?yàn)槌瑫r(shí)自動斷開連接);
? 客戶端繼續(xù)發(fā)送請求,重復(fù)以上步驟。
長輪詢通信過程
改進(jìn)點(diǎn)
? 長輪詢是基于短輪詢上的改進(jìn)版本:減少了客戶端發(fā)起Http連接的開銷,改成在服務(wù)器端主動地去判斷關(guān)注的內(nèi)容是否變化。
基于iframe的長輪詢
? 基于iframe的長輪詢是長輪詢的另一種實(shí)現(xiàn)方案。
實(shí)現(xiàn)原理
? 在頁面中嵌入一個(gè)iframe,地址指向輪詢的服務(wù)器地址,然后在父頁面中放置一個(gè)執(zhí)行函數(shù),比如execute(data);
? 當(dāng)服務(wù)器有內(nèi)容改變時(shí),會向iframe發(fā)送一個(gè)腳本;
? 通過發(fā)送的腳本,主動執(zhí)行父頁面中的方法,達(dá)到推送的效果。
總結(jié)
? 基于iframe的長輪詢底層還是長輪詢技術(shù),只是實(shí)現(xiàn)方式不同,而且在瀏覽器上會顯示請求未加載完成,圖標(biāo)會不停旋轉(zhuǎn),簡直是強(qiáng)迫癥殺手,個(gè)人不是很推薦。
iframe長輪詢
Server-Sent Events(SSE)
? 上面介紹的短輪詢和長輪詢技術(shù),服務(wù)器端是無法主動給客戶端推送消息的,都是客戶端主動去請求服務(wù)器端獲取最新的數(shù)據(jù)。而SSE是一種可以主動從服務(wù)端推送消息的技術(shù)。
? SSE的本質(zhì)其實(shí)就是一個(gè)HTTP的長連接,只不過它給客戶端發(fā)送的不是一次性的數(shù)據(jù)包,而是一個(gè)stream流,格式為text/event-stream。所以客戶端不會關(guān)閉連接,會一直等著服務(wù)器發(fā)過來的新的數(shù)據(jù)流。
實(shí)現(xiàn)原理
? 客戶端向服務(wù)端發(fā)起HTTP長連接,服務(wù)端返回stream響應(yīng)流??蛻舳耸盏絪tream響應(yīng)流并不會關(guān)閉連接而是一直等待服務(wù)端發(fā)送新的數(shù)據(jù)流。
圖片
SSE通信過程
瀏覽器對 SSE 的支持情況
瀏覽器對 SSE 的支持情況
SSE vs WebSocket
? SSE 使用 HTTP 協(xié)議,現(xiàn)有的服務(wù)器軟件都支持。WebSocket 是一個(gè)獨(dú)立協(xié)議。
? SSE 屬于輕量級,使用簡單;WebSocket 協(xié)議相對復(fù)雜。
? SSE 默認(rèn)支持?jǐn)嗑€重連,WebSocket 需要自己實(shí)現(xiàn)。
? SSE 一般只用來傳送文本,二進(jìn)制數(shù)據(jù)需要編碼后傳送,WebSocket 默認(rèn)支持傳送二進(jìn)制數(shù)據(jù)。
? SSE 支持自定義發(fā)送的消息類型。
總結(jié)
? 對于僅需要服務(wù)端向客戶端推送數(shù)據(jù)的場景,我們可以考慮實(shí)現(xiàn)更加簡單的 SSE 而不是直接使用 WebSocket。
WebSocket
? WebSocket 是一種網(wǎng)絡(luò)傳輸協(xié)議,可在單個(gè) TCP 連接上進(jìn)行全雙工通信,位于 OSI 模型的應(yīng)用層。
? WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)??蛻舳撕头?wù)器只需要完成一次握手,兩者之間就可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
實(shí)現(xiàn)原理
? 客戶端發(fā)送一個(gè) HTTP GET 請求到服務(wù)器,請求的路徑是 WebSocket 的路徑(類似 ws://example.com/socket)。請求中包含一些特殊的頭字段,如 Upgrade: websocket 和 Connection: Upgrade,以表明客戶端希望升級連接為 WebSocket。
? 服務(wù)器收到這個(gè)請求后,會返回一個(gè) HTTP 101 狀態(tài)碼(協(xié)議切換協(xié)議)。同樣在響應(yīng)頭中包含 Upgrade: websocket 和 Connection: Upgrade,以及一些其他的 WebSocket 特定的頭字段,例如 Sec-WebSocket-Accept,用于驗(yàn)證握手的合法性。
? 客戶端和服務(wù)器之間的連接從普通的 HTTP 連接升級為 WebSocket 連接。之后,客戶端和服務(wù)器之間的通信就變成了 WebSocket 幀的傳輸,而不再是普通的 HTTP 請求和響應(yīng),客戶端和服務(wù)端相互進(jìn)行通信。
WebSocket通信過程
優(yōu)點(diǎn)
? 實(shí)時(shí)性:WebSocket 提供了雙向通信,服務(wù)器可以主動向客戶端推送數(shù)據(jù),實(shí)現(xiàn)實(shí)時(shí)性非常高,適用于實(shí)時(shí)聊天、在線協(xié)作等應(yīng)用。
? 減少網(wǎng)絡(luò)延遲:與輪詢和長輪詢相比,WebSocket 可以顯著減少網(wǎng)絡(luò)延遲,因?yàn)椴恍枰诿總€(gè)請求之間建立和關(guān)閉連接。
? 較小的數(shù)據(jù)傳輸開銷:WebSocket 的數(shù)據(jù)幀相比于 HTTP 請求報(bào)文較小,減少了在每個(gè)請求中傳輸?shù)拈_銷,特別適用于需要頻繁通信的應(yīng)用。
? 較低的服務(wù)器資源占用:由于 WebSocket 的長連接特性,服務(wù)器可以處理更多的并發(fā)連接,相較于短連接有更低的資源占用。
? 跨域通信:與一些其他跨域通信方法相比,WebSocket 更容易實(shí)現(xiàn)跨域通信。
缺點(diǎn)
? 連接狀態(tài)保持:長時(shí)間保持連接可能會導(dǎo)致服務(wù)器和客戶端都需要維護(hù)連接狀態(tài),可能增加一些負(fù)擔(dān)。
? 不適用于所有場景:對于一些請求-響應(yīng)模式較為簡單的場景,WebSocket 的實(shí)時(shí)特性可能并不是必要的,使用 HTTP 請求可能更為合適。
? 復(fù)雜性:與傳統(tǒng)的 HTTP 請求相比,WebSocket 的實(shí)現(xiàn)和管理可能稍顯復(fù)雜,尤其是在處理連接狀態(tài)、異常等方面。
總結(jié)
? 在本文中我們介紹了IM通信技術(shù)中的常用四種技術(shù):短輪詢、長輪詢、SSE、WebSocket,使用時(shí)可以綜合我們的實(shí)際場景選擇合適的通信技術(shù),在復(fù)雜的應(yīng)用場景中,我們可能需要結(jié)合不同的技術(shù)滿足不同的需求,下面是一些常見的考慮因素:
實(shí)時(shí)性要求
? 如果實(shí)時(shí)性要求較低,短輪詢或長輪詢可能足夠;如果需要實(shí)時(shí)性較高,考慮使用SSE或WebSocket,若僅需要服務(wù)端推送,盡可能考慮SSE。
網(wǎng)絡(luò)和服務(wù)器資源
? 短輪詢和長輪詢可能會產(chǎn)生較多的無效請求,增加帶寬和服務(wù)器負(fù)擔(dān);SSE和WebSocket相對更高效。
個(gè)人簡介
?? 你好,我是 Lorin 洛林,一位 Java 后端技術(shù)開發(fā)者!座右銘:Technology has the power to make the world a better place.