web伺服器端推送技術小結
web伺服器端推送技術小結
技術實現方案:
Ajax輪詢
Ajax長輪詢
websocket
server-sent-events
Ajax輪詢
實踐簡單,利用XHR,通過setInterval定時發送請求,但會造成數據同步不及時及無效的請求,增加後端處理壓力。
Ajax長輪詢
在Ajax輪詢基礎上做的一些改進,在沒有更新的時候不再返回空響應,而且把連接保持到有更新的時候,客戶端向伺服器發送Ajax請求,伺服器接到請求後hold住連接,直到有新消息才返迴響應信息並關閉連接,客戶端處理完響應信息後再向伺服器發送新的請求,通常把這種實現也叫做comet。
通常的做法是,在伺服器的程序中加入一個死循環,在循環中監測數據的變動。當發現新數據時,立即將其輸出給瀏覽器並斷開連接,瀏覽器在收到數據後,再次發起請求以進入下一個周期。
普通Ajax輪詢與基於Ajax的長輪詢原理對比: Ajax
Server-sent-events(SSE)
Server-sent-events(SSE)讓服務端可以向客戶端流式發送文本消息,在實現上,客戶端瀏覽器中增加EventSource對象,使其能通過事件的方式接收到伺服器推送的消息,在服務端,使用長連接的事件流協議,即請求響應時增加新數據流數據格式。
非常適應於後端數據更新頻繁且對實時性要求較高而又不需要客戶端向服務端通信的場景下。
EventSource API
客戶端API使用非常簡單,瀏覽器在支持的情況下會自動處理一切,包括連接管理接收並解析數據到最後觸發DOM事件,開發時只需要關注業務邏輯,EventSource介面還能自動重新連接並跟蹤最近接收的消息,還可以向伺服器發送上一次接收到消息的ID,以便伺服器重傳丟失的消息並恢複流。
Event Stream協議
SSE事件流以流式HTTP響應請求,客戶端發起普通的HTTP請求,伺服器以自定義的text/event-stream內容類型響應,然後通過事件傳遞數據。
響應頭
響應數據格式
id: 123
retry: 10000
event: userlogin
data: {「username」: 「John123」}
客戶端通過EventSource介面發起連接,伺服器以text/event-stream內容類型響應,可設置中斷後重連時間間隔retry,數據通過字元串的方式賦值給data欄位,也可以指定消息類型給event欄位。在客戶端EventSource介面通過檢查換行分隔符來解析到來的數據流,從data欄位中獲取數據,檢查可選的ID和類型,最後分配事件告知應用,如果存在某個類型,觸發自定義的事件回調,否則就會調用通用的onmessage回調。
為了在連接中斷時恢復中斷過程中丟失的消息,伺服器在響應時可以給每條消息關聯任意的ID字元串,瀏覽器會自動記錄最後一次接收到消息ID,並在發送重新連接請求時自動在HTTP請求頭中追加Last-Event-ID,這樣就可以標識中斷過程中丟失的消息並重新發送給客戶端。
優點
基於現有http協議,實現簡單
斷開後自動重聯,並可設置重聯超時
派發任意事件
跨域並有相應的安全過濾
缺點
只能單向通信,伺服器端向客戶端推送事件
事件流協議只能傳輸UTF-8數據,不支持二進位流。
IE下目前所有不支持EventSource
Tip 如果代理伺服器或中間設備不支持SSE,會導致連接失效,正式環境中使用通過TLS協議發送SSE事件流。
WebSocket
WebSocket可以實現與客戶端與伺服器雙向,基於消息的文本或二進位數據通信,主要包括兩個部分,客戶端WebSocket API及WebSocket協議。
WebSocket是HTML5出的東西(協議),也就是說HTTP協議沒有變化,或者說沒關係,但HTTP是不支持持久連接的(長連接,循環連接的不算)首先HTTP有1.1和1.0之說,也就是所謂的keep-alive,把多個HTTP請求合併為一個,但是Websocket其實是一個新協議,跟HTTP協議基本沒有關係,只是為了兼容現有瀏覽器的握手規範而已。
WebSocket API
瀏覽器提供的WebSocket API很簡單,使用時無需關心連接管理和消息處理等底層細節,只需要發起連接,綁定相應的事件回調即可。
WebSocket資源URL採用了自定議模式,沒有使用http是為了在非http協議場景下也能使用,wss表示使用加密信道通信(TCP + TLS),支持接收和發送文本和二進位數據。
WebSocket 協議
WebSocket通信協議包含兩個部分,一是開放性HTTP握手連接協商連接參數,二是二進位消息分幀機制(接收消息的文本和二進位數據傳輸)。它是一個獨立完善的協議,也可以在瀏覽器之外實現。
HTTP升級協商
WebSocket協議提供了很多強大的特性:基於消息的通信、自定義的二進位分幀層、子協議協商、可選的協議擴展,等等。即在交換數據之前,客戶端必須與伺服器協商適當的參數以建立連接。
利用HTTP完成握手有幾個好處。首先,讓WebSockets與現有HTTP基礎設施兼容:WebSocket伺服器可以運行在80和443 埠上,這通常是對客戶端唯一開放的埠。其次,讓我們可以重用並擴展HTTP的Upgrade流,為其添加自定義的WebSocket首部,以完成協商。
請求頭信息
Connection:Upgrade
Sec-WebSocket-Key:eDCPPyPQZq7PiwRcx8SPog==
Sec-WebSocket-Version:13
Upgrade:websocket
響應頭信息
HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Sec-WebSocket-Accept:/ZVAP3n6XuqDUoDp416PYUO+ZJc=
Upgrade:websocket
最後,前述握手完成後,如果握手成功,該連接就可以用作雙向通信信道交換WebSocket消息。到此,客戶端與伺服器之間不會再發生HTTP通信,一切由WebSocket 協議接管。
服務端實現
Node (Socket.IO, WebSocket-Node, ws)
Java (Jetty)
Python (Tornado, pywebsocket)
…
使用場景
適合於對數據的實時性要求比較強的場景,如通信、股票、Feed、直播、共享桌面,特別適合於客戶端與服務頻繁交互的情況下,如實時共享、多人協作等平台。
優點
真正的全雙工通信
支持跨域設置(Access-Control-Allow-Origin)
缺點
採用新的協議,後端需要單獨實現
客戶端並不是所有瀏覽器都支持
代理伺服器會有不支持websocket的情況
無超時處理
更耗電及佔用資源
TIP 代理、很多現有的HTTP中間設備可能不理解新的WebSocket協議,而這可能導致各種問題,使用時需要注意,可以使藉助TLS,通過建立一條端到端的加密信道,可以讓WebSocket通信繞過所有中間代理。
參考:
1.web伺服器端推送技術簡介
2.goeasy.io
3.Nodejs和一個簡單的web頁面消息推送服務
4.socket.io
TAG:NOJSer |