天天看點

websocket原理說明

衆所周知,Web應用的通信過程通常是用戶端通過浏覽器發出一個請求,伺服器端接收請求後進行處理并傳回結果給用戶端,用戶端浏覽器将資訊呈現。這種機制對于資訊變化不是特别頻繁的應用可以良好支撐,但對于實時要求高、海量并發的應用來說顯得捉襟見肘,尤其在目前業界移動網際網路蓬勃發展的趨勢下,高并發與使用者實時響應是Web應用經常面臨的問題,比如金融證券的實時資訊、Web導航應用中的地理位置擷取、社交網絡的實時消息推送等。

傳統的請求-響應模式的Web開發在處理此類業務場景時,通常采用實時通訊方案。比如常見的輪詢方案,其原理簡單易懂,就是用戶端以一定的時間間隔頻繁請求的方式向伺服器發送請求,來保持用戶端和伺服器端的資料同步。其問題也很明顯:當用戶端以固定頻率向伺服器端發送請求時,伺服器端的資料可能并沒有更新,帶來很多無謂請求,浪費帶寬,效率低下。

基于Flash,AdobeFlash通過自己的Socket實作完成資料交換,再利用Flash暴露出相應的接口給JavaScript調用,進而達到實時傳輸目的。此方式比輪詢要高效,且因為Flash安裝率高,應用場景廣泛。然而,移動網際網路終端上Flash的支援并不好:IOS系統中無法支援Flash,Android雖然支援Flash但實際的使用效果差強人意,且對移動裝置的硬體配置要求較高。2012年Adobe官方宣布不再支援Android4.1+系統,宣告了Flash在移動終端上的死亡。

傳統的Web模式在處理高并發及實時性需求的時候,會遇到難以逾越的瓶頸,需要一種高效節能的雙向通信機制來保證資料的實時傳輸。在此背景下,基于HTML5規範的、有Web TCP之稱的 WebSocket應運而生。早期HTML5并沒有形成業界統一的規範,各個浏覽器和應用伺服器廠商有着各異的類似實作,如IBM的MQTT、Comet開源架構等。直到2014年,HTML5終于塵埃落地,正式落實為實際标準規範,各個應用伺服器及浏覽器廠商逐漸開始統一,在 JavaEE7中也實作了WebSocket協定。至此無論是用戶端還是服務端的WebSocket都已完備。使用者可以查閱HTML5規範,熟悉新的HTML協定規範及WebSocket支援。

WebSocket 機制

以下簡要介紹一下WebSocket的原理及運作機制。

WebSocket是HTML5下一種新的協定。它實作了浏覽器與伺服器全雙工通信,能更好的節省伺服器資源和帶寬并達到實時通訊的目的。它與HTTP一樣通過已建立的TCP連接配接來傳輸資料,但是它和HTTP最大不同是:

  • WebSocket是一種雙向通信協定。在建立連接配接後,WebSocket伺服器端和用戶端都能主動向對方發送或接收資料,就像Socket一樣;
  • WebSocket需要像TCP一樣,先建立連接配接,連接配接成功後才能互相通信。

傳統HTTP用戶端與伺服器請求響應模式如下圖所示:

websocket原理說明

WebSocket模式用戶端與伺服器請求響應模式如下圖:

websocket原理說明

上圖對比可以看出,相對于傳統HTTP每次請求-應答都需要用戶端與服務端建立連接配接的模式,WebSocket是類似Socket的TCP長連接配接通訊模式。一旦WebSocket連接配接建立後,後續資料都以幀序列的形式傳輸。在用戶端斷開WebSocket連接配接或Server端中斷連接配接前,不需要用戶端和服務端重新發起連接配接請求。在海量并發及用戶端與伺服器互動負載流量大的情況下,極大的節省了網絡帶寬資源的消耗,有明顯的性能優勢,且用戶端發送和接受消息是在同一個持久連接配接上發起,實時性優勢明顯。

相比HTTP長連接配接,WebSocket有以下特點:

  • 是真正的全雙工方式,建立連接配接後用戶端與伺服器端是完全平等的,可以互相主動請求。而HTTP長連接配接基于HTTP,是傳統的用戶端對伺服器發起請求的模式。
  • HTTP長連接配接中,每次資料交換除了真正的資料部分外,伺服器和用戶端還要大量交換HTTP header,資訊交換效率很低。Websocket協定通過第一個request建立了TCP連接配接之後,之後交換的資料都不需要發送 HTTP header就能交換資料,這顯然和原有的HTTP協定有差別是以它需要對伺服器和用戶端都進行更新才能實作(主流浏覽器都已支援HTML5)。此外還有 multiplexing、不同的URL可以複用同一個WebSocket連接配接等功能。這些都是HTTP長連接配接不能做到的。

下面再通過用戶端和服務端互動的封包對比WebSocket通訊與傳統HTTP的不同點:

在用戶端,new WebSocket執行個體化一個新的WebSocket用戶端對象,請求類似 ws://yourdomain:port/path 的服務端WebSocket URL,用戶端WebSocket對象會自動解析并識别為WebSocket請求,并連接配接服務端端口,執行雙方握手過程,用戶端發送資料格式類似:

GET /webfin/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: http://localhost:8080
Sec-WebSocket-Version: 13
           

可以看到,用戶端發起的WebSocket連接配接封包類似傳統HTTP封包,

Upgrade:websocket

參數值表明這是WebSocket類型請求,

Sec-WebSocket-Key

是WebSocket用戶端發送的一個 base64編碼的密文,要求服務端必須傳回一個對應加密的

Sec-WebSocket-Accept

應答,否則用戶端會抛出

Error during WebSocket handshake

錯誤,并關閉連接配接。

服務端收到封包後傳回的資料格式類似:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
           

Sec-WebSocket-Accept

的值是服務端采用與用戶端一緻的密鑰計算出來後傳回用戶端的,

HTTP/1.1 101 Switching Protocols

表示服務端接受WebSocket協定的用戶端連接配接,經過這樣的請求-響應處理後,兩端的WebSocket連接配接握手成功, 後續就可以進行TCP通訊了。使用者可以查閱WebSocket協定棧了解WebSocket用戶端和服務端更詳細的互動資料格式。

在開發方面,WebSocket API 也十分簡單:隻需要執行個體化 WebSocket,建立連接配接,然後服務端和用戶端就可以互相發送和響應消息。在WebSocket 實作及案例分析部分可以看到詳細的 WebSocket API 及代碼實作。

騰訊雲公網有日租類型七層負載均衡轉發部分支援Websocket,目前包括英魂之刃、銀漢遊戲等多家企業已接入使用。當出現不相容問題時,請修改websocket配置,websocket server不校驗下圖中圈出的字段:

websocket原理說明

一個使用WebSocket應用于視訊的業務思路如下:

  • 使用心跳維護websocket鍊路,探測用戶端端的網紅/主播是否線上
  • 設定負載均衡7層的proxy_read_timeout預設為60s
  • 設定心跳為50s,即可長期保持Websocket不斷開

繼續閱讀