除了 Websocket ,服務端還有什么辦法能向瀏覽器主動推送資訊?
- 前言
- 端倪
- Server-Sent Events 是什么?
- Server-Sent Events 與 Websocket 對比
- 總結
前言
打工的時候,偶爾在閑暇時刻偷偷打開一下股票網站,看看今天有沒有賺錢,說不定哪天一夜暴富,這是我現在唯一的盼頭……

今天我一如往常打開熟悉的“XX財富網”,輸入熟悉的股票代碼,點開我前幾天剛買入的“XXX”……

看著冒著綠光并且一閃一閃的螢屏,我陷入了沉思……

我恍惚了一下,心想這實時重繪的資料,是后端通過websocket推過來的嗎?
于是我F12看了一下,沒有 websocket 連接啊!

難道除了 Websocket 還有別的辦法能夠讓后端向前端主動推送訊息?
我馬上想到了 http2.0 的 server push ,但是想了想又覺得不太可能,因為 http2.0 的push并不是這個意思,
http2.0 的 server push 指的是:服務器還沒有收到瀏覽器的請求,服務器就把各種資源推送給瀏覽器,比如,瀏覽器只請求了 index.html,但是服務器發現 index.html 內容里面需要用到 style.css、example.png,于是服務器在瀏覽器請求 index.html時順便把 style.css、example.png 也一起發送給瀏覽器,這樣的話,只需要一輪 HTTP 通信,瀏覽器就得到了全部資源,提高了性能,
所以很明顯,http2.0 的 server push 只是復用其中一條http連接順便把后續需要發送的一些靜態資源提前發給了瀏覽器,并不適用于這種推送動態資料的場景(比如股票漲跌資料實時重繪、直播彈幕推送等),
那服務器究竟是怎么實時推送了股票相關的資料呢?
端倪
于是我點開了 Fetch/XHR 看看到底是何方神圣,在不斷推送資料,于是我發現了這幾個請求的內容好像不斷地在重繪……
從下圖可以看到一秒鐘推送好幾條資料過來(現在是十一點半,我打開了美股)

查看這幾個http請求,很容易就發現請求頭和回應頭的 Content-Type 和 Accept 跟其它普通的http請求不太一樣,

很明顯,這個服務端推送,跟這個 text/event-stream 關系很大,

于是我去查了一下相關資料,果不其然……服務器向瀏覽器推送資訊,除了 WebSocket,還有一種方法:Server-Sent Events,
Server-Sent Events 是什么?
Server-Sent Events,服務器發送事件,簡稱SSE,是一種 HTML 5 事件通知,它允許網頁獲得來自服務器的更新,
嚴格來說,HTTP 協議是沒有辦法做到服務器主動推送資訊的,但是有一種變通的方法可以做到,那就是服務器向客戶端宣告接下來要發送的是流資訊(streaming),
也就是說,發送的不是一次性的資料包,而是一個資料流,會連續不斷地發送過來,這時,客戶端不會關閉連接,會一直等著服務器發過來的新的資料流,視頻播放就是這樣的例子,本質上,這種通信就是以流資訊的方式,完成一次用時很長的下載,
SSE 就是利用這種機制,使用流資訊向瀏覽器推送資訊,它基于 HTTP 協議,目前除了 IE/Edge,其他瀏覽器都支持,
Server-Sent Events 與 Websocket 對比
既然能讓服務器主動向瀏覽器推送資訊,那我們肯定會想到讓websocket來跟它做做對比,
總的來說,Websocket 應該是更強大、更靈活、應用更廣泛的,因為它是全雙工通信,可以雙向通信;但是SSE是單向通道,只能服務器向瀏覽器發送,因為流資訊本質上就是下載,如果瀏覽器向服務器發送資訊,就變成了另一次 HTTP 請求,

但是,SSE也有自己的優點,
- SSE 使用 HTTP 協議,現有的服務器軟體都支持,WebSocket 是一個獨立協議,
- SSE 比較輕量級,使用較簡單;WebSocket 協議相對來說比較復雜,
- SSE 默認支持斷線重連,而WebSocket 需要自己實作,
- SSE 一般只用來傳送文本,二進制資料需要編碼后傳送,WebSocket 默認支持傳送二進制資料,
- SSE 支持自定義發送的訊息型別,
所以 SSE 和 Websocket 適合不同的使用場景,
遲點有空的時候寫個demo試試,
總結
- 除了 Websocket ,服務端還能通過 SSE 向瀏覽器主動推送訊息,其本質上就是一個基于 HTTP 的流,
- 今天的工不白打,股市雖綠,但我因此識訓了一個冷門的知識點
安慰自己,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/307204.html
標籤:其他
