Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polling vs Websocket vs Server-Sent Events #15

Open
JeffKko opened this issue Mar 8, 2021 · 0 comments
Open

Polling vs Websocket vs Server-Sent Events #15

JeffKko opened this issue Mar 8, 2021 · 0 comments
Labels

Comments

@JeffKko
Copy link
Owner

JeffKko commented Mar 8, 2021

Preface

最近在公司的 member center 有一個 notification center 的 idea

身為一個 類電商 + 類貨運的網站, 有這種 feature 確實會更好用,
real-time 的特性, 也可以在需付款或是到貨時即時的通知使用者

Polling vs Websocket vs Server-Sent Events

在消化了大量資訊後了解到 web 能實現的方法大概有這三種

  • Polling

  • Websocket

  • Server-Sent Events

Polling

client 每隔幾秒就向 server 發出 request

function Polling() {
  fetch(url)
    .then(data => {})
    .catch(err => {
      console.log(err)
    })
}
setInterval(polling, 5000)
  • 優點: 簡單暴力, 使用http協定基本上 client & server 都不用另外做特別的處理

  • 缺點:

    1. 是最消耗資源的方式, client端要一直重複建立 Tcp 會非常消耗資源
    2. 實際上比較像是 client pull 而不是 server push, 無法做到真正的同步

Long Polling (COMET)

Polling的進化版, client 發出 request 之後, 不會立刻返回請求, 有數據更新或 timeout時才會返回

function LongPolling() {
  fetch(url)
    .then(LongPolling)
    .catch(err => {
      LongPolling()
      console.log(err)
    })
}
LongPolling()
  • 優點: 相比普通的 polling, 節省了很多請求次數, 相對節省資源

  • 缺點:

    1. 還是一樣要由 client 發起連接的建立, 消耗資源
    2. 實際上比較像是 client pull 而不是 server push, 無法做到真正的同步

另外還有一種方式是利用 iframe 實現的, 但是這邊就不詳述了

Websocket

這是一個可以透過單個TCP連接後, 提供全雙工通信通道的通信協議,

可以在 client 和 server 之間維持持久性的連接

window.WebSocket = window.WebSocket || window.MozWebSocket

  const connection = new WebSocket('ws://localhost:8080/githubEvents')

  connection.onopen = function () {
    // connection is opened and ready to use
  }

  connection.onerror = function (error) {
    // an error occurred when sending/receiving data
  }

  connection.onmessage = function (message) {
    // try to decode json (I assume that each message
    // from server is json)
    try {
      const githubEvent = JSON.parse(message.data) // display to the user appropriately
    } catch (e) {
      console.log('This doesn\'t look like a valid JSON: ' + message.data)
      return
    }
    // handle incoming message
  }
  • 優點: 沒有多餘的效能浪費

  • 缺點:

    1. client, server 都需要自行處理 http 已經處理好的問題
    2. 在需要多路同步傳輸時, 實現起來有其複雜度

Server-Sent Events (SSE)

SSE 是一種單向的訂閱/推播機制, HTML5的標準中提供了一個Web API: EventSource

在TCP連接後, 就可以建立永久性的連接, server 可以一直將數據傳送到 client端

SSE也是一種基於 http 的實作, 所以也可以相容於 http/2, 回應的 content-type 是較為特殊的 content-type: text/event-stream

const source = new EventSource('/sse')

source.addEventListener('message', function (e) {
  console.log(e.data)
}, false)

source.addEventListener('my_msg', function (e) {
  process(e.data)
}, false)

source.addEventListener('open', function (e) {
  console.log('open sse')
}, false)

source.addEventListener('error', function (e) {
  console.log('error')
})
  • 優點:

    1. 輕量, 實作相較於 websocket 簡單很多
    2. 開箱既用的實現支援 http/2
  • 缺點: IE不支援

High Level Comparison

一張圖詳細了解 Polling vs SSE

image

Conclusion

從各方面比較下來, SSE是一個綜合起來最輕量, 開發容易, 效能又好的一個選擇

SSE 基本上可以很好的取代 polling, 很適合做這些類似的應用

  • 即時股價資訊
  • 通知/推文/新聞資訊
  • 監控系統的 monitor

不過, 若 client 與其他 client 也需要平凡的做資料交換的話, 像是多人的網路遊戲, 這種大量數據的雙向溝通還是需要 Websocket 來處理會比較適合

  • 相容性: Polling > Long Polling > SSE > WebSocket

  • 性能上: WebSocket > SSE > Long Polling > Polling

最後, 我自己也用了 SSE 簡單做了一個 Chat Room,
Github Repo

Reference Articles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant