WebSocket 與 Polling , Long-Polling , Streaming 的比較!

阿里雲最近在作活動,低至2折,有興趣能夠看看:
https://promotion.aliyun.com/...

爲了保證的可讀性,本文采用意譯而非直譯。html

Web Sockets定義了一種在經過一個單一的 socket 在網絡上進行全雙工通信的通道。它不只僅是傳統的 HTTP 通信的一個增量的提升,尤爲對於實時、事件驅動的應用來講是一個飛躍。前端

HTML5 Web Sockets 相對於老的技術(在瀏覽器中模擬全雙工鏈接的複雜技術)有了如此巨大的提高,以至於谷歌的 Ian Hickson(HTML5 說明書的總編)說:git

想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!github

「將數據的千字節減小到2字節……並將延遲從150ms減小到50ms,這遠遠超過了邊際效應。」事實上,僅這兩個因素就足以讓谷歌對 Web Sockets 字產生濃厚的興趣。

讓咱們來看看 HTML5 Web Sockets 是如何經過與傳統的解決方案進行比較,從而極大地減小沒必要要的網絡流量和延遲的web

Polling (輪詢), Long-Polling (長輪詢), and Streaming (串流)

一般,當一個瀏覽器訪問一個網頁時,會向擁有這個頁面的服務器發送一個HTTP請求。Web 服務器接受這個請求並返回一個響應。segmentfault

在許多狀況下——例如,股票價格、新聞報道、機票銷售、交通模式、醫療設備讀數等等——瀏覽器渲染頁面時,響應可能已通過時,若是你想得到最新的「實時」信息,你能夠不斷手動刷新該頁面,但這顯然不是一個很好的解決方案。後端

當前嘗試提供實時 Web 應用程序其主要圍繞輪詢和其餘服務器端推送技術,其中最引人注目的是 Comet,它會延遲完成 HTTP 響應以將消息傳遞到客戶端。基於 Comet 的推送通常採用 JavaScript 實現並使用長鏈接或流等鏈接策略。瀏覽器

comet: 基於 HTTP 長鏈接的「服務器推」技術。基於這種架構開發的應用中,服務器端會主動以異步的方式向客戶端程序推送數據,而不須要客戶端顯式的發出請求。Comet 架構很是適合事件驅動的 Web 應用,以及對交互性和實時性要求很強的應用,如股票交易行情分析、聊天室和 Web 版在線遊戲等。

Polling (輪詢)

經過輪詢,瀏覽器按期發送 HTTP 請求並當即接收響應,這項技術是瀏覽器首次嘗試傳遞實時信息。顯然,若是消息傳遞的確切時間間隔已知,這是一個很好的解決方案,由於能夠在服務器上先把須要發送的信息準備好以後在發送給客戶端。然而,實時數據一般是不可預測的,這必然形成許多沒必要要的請求,所以,在低頻率消息的狀況下,許多鏈接被沒必要要地打開和關閉的。安全

Long-Polling (長輪詢)

長輪詢是讓服務器在接收到瀏覽器所送出 HTTP 請求後,服務器會等待一段時間,若在這段時間裏面服務器有新的消息,它就會把最新的消息傳回給瀏覽器,若是等待的時間到了以後也沒有新的消息的話,就會送一個迴應給瀏覽器,告知瀏覽器消息沒有更新。服務器

雖然輪詢能夠減小產生本來輪詢形成網絡帶寬浪費的狀況,可是,若是在資料更新頻繁的情況下,長時間輪詢不傳統比傳統的輪詢有效率,並且有時候資料量很大時,會形成連續的輪詢不斷產生,反而會更糟糕。

圖片描述

串流(Streaming)

串流 (streaming) 是讓服務器在接收到瀏覽器所送出的 HTTP 請求後,當即產生一個迴應瀏覽器的鏈接,而且讓這個鏈接持續一段時間不要中斷,而服務器在這段時間內若是有新的消息,就能夠透過這個鏈接將消息立刻傳送給瀏覽器。

然而,因爲流仍然封裝在 HTTP 中,介入的防火牆和代理服務器可能會選擇緩衝響應,從而增長消息傳遞的延遲。所以,若是檢測到緩衝代理服務器,流式 Comet 解決方案將退回到長輪詢。或者,可使用TLS (SSL)鏈接來防止響應被緩衝,可是這種狀況下建立和銷燬每個鏈接將消耗更多的可用的服務器資源。

TLS:安全傳輸層協議(TLS)用於在兩個通訊應用程序之間提供保密性和數據完整性。 該協議由兩層組成: TLS 記錄協議(TLS Record)和 TLS 握手協議(TLS Handshake)。

SSL:SSL(Secure Sockets Layer 安全套接層),及其繼任者傳輸層安全(Transport Layer
Security,TLS)是爲網絡通訊提供安全及數據完整性的一種安全協議。TLS與SSL在傳輸層對網絡鏈接進行加密。

最後,全部這些提供實時數據的方法都會引入 HTTP 請求和響應報頭,這些報頭包含大量額外的、沒必要要的報頭數據,並會帶來延遲。

最重要的是,全雙工鏈接須要的不只僅是從服務器到客戶端的下行鏈接。爲了在半雙工HTTP上模擬全雙工通訊,當今的許多解決方案使用兩個鏈接:一個用於下行,一個用於上行,這兩個鏈接的維護和協調在資源消耗方面引入了大量開銷,並增長了許多複雜性。

簡單地說,HTTP 不是爲實時、全雙工通訊而設計的,能夠在下面的圖中看到,該圖展現了構建 Comet Web 應用(在半雙工的 HTTP 上使用訂閱模式實時獲取後端數據)的複雜性。

Comet 應用程序的複雜性

當試圖將 Comet 的解決方案擴充系統的規模時會變得更糟。在 HTTP 模擬全雙工的瀏覽器通信易出錯、複雜並且複雜度沒法下降。儘管最終用戶可能正在體驗相似於實時 Web應用程序的服務,但這種 「實時」 體驗的代價高得驚人。這個代價是,付出額外的延遲,沒必要要的網絡流量和 CPU性能的影響上。

HTML5 WebSocket 通訊協議

在 HTML5 規範的通訊部分中定義,HTML5 Web Sockets 表明了全雙工的網絡交互的下一個演變 —— 一個全雙工、雙向的通訊通道,經過 Web 上的單個套接字進行操做。

HTML5 Web Sockets 提供了一個真正的標準,可使用它來構建可擴展的實時 Web 應用程序。此外,因爲它提供了瀏覽器本地的套接字,所以避免了 Comet 解決方案容易出現的許多問題。 Web Socket s移除了開銷大幅度減輕了複雜度。

爲了創建WebSocket鏈接,客戶端和服務器在首次握手時從 HTTP 協議升級到 WebSocket 協議,以下圖所示:

示例1 - WebSocket握手(瀏覽器請求和服務器響應)

圖片描述

熟悉 HTTP 的可能會發現,這段相似 HTTP 協議的握手請求中,多了幾個東西:

Upgrade: websocket
Connection: Upgrade

這個就是 Websocket 的核心了,告訴 ApacheNginx 等服務器:發起的是 Websocket協議,使用對應的Websocket協議處理,而不是使用 HTTP 協議。

一旦創建,WebSocket 數據幀能夠在客戶端和服務器之間以全雙工模式來回發送。文本和二進制幀均可以發送全雙工,在同一時間向任意方向發送,數據的最小幀只有兩個字節。

在文本幀的狀況下,每一個幀以 0x00 元組開頭,以 0xFF 元組結束,中間包含 UTF-8 數據,WebSocket 文本幀使用終止符,而二進制幀使用長度前綴。

注意:儘管 Web Sockets 協議已經準備好支持各類客戶端集,可是它不能將原始二進制數據交付給 JavaScript,由於 JavaScript 不支持字節類型。所以,若是客戶端是 Javascript 的,二進制數據將被忽略 —— 可是能夠把它發送給其它支持二進制的客戶端。

Comet vs. HTML5 WebSocket

那麼在非必要的網絡傳輸和延遲性上究竟減小了多少?讓比較一下長鏈接應用和 WebSocket 應用。

對於輪詢示例,我建立了一個簡單的 Web 應用程序,其中 Web 頁面使用傳統的發佈/訂閱模型從RabbitMQ 消息隊列中獲取實時股票信息。

它經過輪詢駐留在 web 服務器上的 Java Servlet 來實現這一點。RabbitMQ 消息隊列從虛構的持續改變股票價格的股票價格服務接收數據。

Web 頁面鏈接並訂閱特定的股票通道(message broker上的主題),並使用 XMLHttpReques t每秒輪詢更新一次。當接收到更新時,執行一些計算,股票數據顯示在一個表中,以下圖所示。

一個JavaScript股票應用

注意:後臺股票服務實際上每秒會產生大量股票價格更新,所以每秒輪詢一次實際上比使用Comet 長輪詢解決方案更爲謹慎,後者會致使一系列持續輪詢,這裏輪詢有效的節制了數據更新。

這一切看起來都很好,但從內部看,這個應用程序有一些嚴重的問題。在 Mozilla Firefox 中使用 Firebug(一個火狐插件——能夠對網頁進行deb、跟蹤加載頁面和執行腳本的時間),能夠看到 GET 請求每隔一秒就會鏈接服務器。打開Live HTTP Headers(另一個火狐插件——能夠顯示活躍 HTTP 頭傳輸)暴露了每個鏈接上巨大數量的頭開銷(header overhead)。下面的例子展現了一個請求和響應的頭信息。

事例二:HTTP request header

圖片描述

事例三:HTTP response header

圖片描述

只是爲了好玩,我數了數全部的字符。總的 HTT P請求和響應頭信息開銷包含 871 字節,甚至不包括任何數據 !固然,這只是一個示例,能夠擁有少於 871 字節的頭數據,可是我也看到過頭數據超過 2000 字節的狀況。

在這個示例應用程序中,典型股票標題信息僅僅20個字符長。正如所看到的,它實際上被過多的頭信息淹沒了,而頭信息甚至在一開始就不是必需的!

那麼當你把這個應用部署到大用戶量的場景下會怎麼樣? 讓咱們在三個不一樣的場景中對比與此輪詢應用程序關聯的 HTTP 請求和響應頭數據的網絡吞吐量。

  • 場景一:每秒 1000 個客戶端輪詢,每秒的網絡流量是 6.6 M
  • 場景二:每秒 10000 個客戶端輪詢,每秒的網絡流量是 66 M
  • 場景三:每秒 100000 個客戶端輪詢,每秒的網絡流量是 660 M

這是大量沒必要要的網絡吞吐量,要是咱們能經過網絡獲得必要的數據就行了,此時就可使用 HTML5 Web Sockets!

我從新構建了應用程序以使用 HTML5 Web Sockets,在 Web 頁面中添加了一個事件處理程序來異步偵聽來來自於代理的股票更新信息。

。每個信息都是一個WebSocket幀,只有兩個字節的開銷(而不是871字節)! 看看這如何影響咱們的三個用例中的網絡吞吐量開銷。

  • 場景一:每秒 1000 個客戶端輪詢,每秒的網絡流量是 0.015 M
  • 場景二:每秒 10000 個客戶端輪詢,每秒的網絡流量是 0.153 M
  • 場景三:每秒 100000 個客戶端輪詢,每秒的網絡流量是 .1526 M

以下圖所示,與輪詢解決方案相比,HTML5 Web Sockets大大減小了沒必要要的網絡流量。

輪詢方案和WebSocket應用在非必要網絡消耗上的比較

那麼延遲的減多少呢? 請看下圖:

在上半部分,能夠看到半雙工輪詢解決方案的延遲。在本例中,假設消息從服務器傳輸到瀏覽器須要50毫秒,那麼輪詢應用程序將引入大量額外的延遲,由於在響應完成時必須將新請求發送到服務器。這個新請求須要另外一個50ms,在此期間服務器不能向瀏覽器發送任何消息,從而致使額外的服務器內存消耗。

在圖的下半部分,能夠看到 WebSocket 解決方案下降了延遲。一旦鏈接升級到 WebSocket,消息就能夠在到達時從服務器流到瀏覽器。消息從服務器傳輸到瀏覽器仍然須要 50 毫秒,可是WebSocket 鏈接仍然打開,所以不須要向服務器發送另外一個請求。

輪詢和WebSocket應用程序之間的延遲比較

WebSocke 瀏覽器支持狀況

clipboard.png

總結

HTML5 Web Sockets 在實時網絡的擴展性上向前邁出了一大步。正如在本文中看到的, HTML5 Web Sockets能夠提供 500:1 甚至 1000:1 的非必要HTTP頭信息傳輸的變少,以及 3:1 延遲性的下降。這不只僅是個進步,它是巨大的一個飛躍!

原文:

http://www.websocket.org/quan...

你的點贊是我持續分享好東西的動力,歡迎點贊!

交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

https://github.com/qq44924588...

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png

相關文章
相關標籤/搜索