惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
aimingoo的专栏
aimingoo的专栏
I
InfoQ
C
Check Point Blog
IT之家
IT之家
MyScale Blog
MyScale Blog
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
Last Week in AI
Last Week in AI
GbyAI
GbyAI
P
Proofpoint News Feed
量子位
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
B
Blog
T
The Blog of Author Tim Ferriss
H
Help Net Security
云风的 BLOG
云风的 BLOG

Nic Lin's Blog

謝明真 - 高效領導力的課後筆記 NFT 開發實戰!基礎智能合約入門 (3) NFT 開發實戰!基礎智能合約入門 (2) NFT 開發實戰!基礎智能合約入門 (1) 如何自我檢測 log4j CVE 漏洞 Rails 如何在資料寫入時記錄來源 IP 位置 如何經營工程師 Youtube 頻道 - Part 8 營收篇 如何經營工程師 Youtube 頻道 - Part 7 酸民文化篇 如何經營工程師 Youtube 頻道 - Part 5 設備器材篇 如何經營工程師 Youtube 頻道 - Part 4 後製剪輯篇 如何經營工程師 Youtube 頻道 - Part 3 文案企劃篇 如何經營工程師 Youtube 頻道 - Part 2 設備器材篇 如何經營工程師 Youtube 頻道 - Part 1 制訂頻道方向篇 如何經營工程師 Youtube 頻道 - Part 0 Rails 中避免 race condition 的最佳實踐(二) Rails 中避免 race condition 的最佳實踐(一) 10 分鐘整合 google sheet 做自動化開發功能週報 經營 Side Project 300 天所帶來的收穫及挑戰 我的 Youtube 影片製作流程 API 設計時必須注意的 HTTP header 底線問題 如何提升你的程式可讀性之實務技巧(三) 如何提升你的程式可讀性之實務技巧(二) 如何提升你的程式可讀性之實務技巧(一) Ruby 中使用 freeze 優化效能的時機 避免 React 中的 useEffect 無限 render 在 Rails 內輕量使用 Vue Component 的最佳實踐 如何在區域網路用 Docker 架設有 SSL 的 Gitlab 從被問到問人,那些我常問的面試問題 [Rails] 如何漂亮寫出可維護的 query (Maintainable Rails Query) 在已知長度情況下優化 slice 的性能
獲得實時更新的方法(Polling, Comet, Long Polling, WebSock...
Nic Lin · 2017-10-28 · via Nic Lin's Blog

獲得實時更新的方法(Polling, Comet, Long Polling, WebSocket)

在 HTTP 協議上,只能由 Client 發起請求,等候 Server 端回應,然後獲得資料,來讓當前頁面更新。

但 Server 端是無法主動發起回應的,譬如說,當某討論串下面的留言更新了,要發起通知讓所有人的通知欄顯示一則未讀廣播,Server 端無法主動向所有正在線上的使用者進行廣播。

這時候就有幾種方法可以實作

Polling

早期的作法通常都是用 Javascript 來實作輪詢(Polling)的方式獲得 Server 端的最新資料。

利用 Javascript 中的 setIntervalsetTimeout 在固定的時間內向 Server 端發起 Request 以 JSON 或 AJAX(xhr)的方式取得最新的資料。

備註: setTimeout 是較好的選擇,請參考 [javascript] 深入了解 setTimeout() 與 setInterval() 的不同之處

不過這麼做的好處是容易實現,也沒有其他瀏覽器的延伸問題,最主要的缺點就是造成資源的浪費以及負擔,因為你不知道 Server 端的資料何時會有更新,再沒有更新的情況下你一樣要發起 HTTP 請求,就會有浪費網路資源的狀況,如果是效能較差的裝置例如智慧型手機,可能就會有耗電、使用上卡頓的狀況發生。

Comet

Comet 如果要翻譯成中文是「彗星」的意思,他的作法是把發出的 Request 像彗星的尾巴一樣拉的很長(正常的 Request 很快就結束),這樣一來就可以讓伺服器保持連線的狀態,持續讓 Server 端 Response 資料回來,這樣的作法其實就是把 Polling 做在 Server 端。

但這樣的作法會把傳統的 Web Server 如 Apache 的連線給佔住,所以必須要配合 non-Blocking IO 的 Web Server 才能運作。

Long Polling

長時間輪詢的作法是 Comet 演化過後的方式,也是目前 Facebook、Plurk 實現動態更新的方法。

這樣的作法是發一個長時間等待的 Request,當 Server 端有資料 Response 時立刻斷掉、接著在發一個新的 Request。

與 Polling 不同之處的在於他比較有效率,可以等到 Timeout 或拿到新資料的時候在重新發送,相對之下減少很多網路資源的浪費。

加上通常是 Client 在傳遞資料(每次發 Request 時)以及沒有瀏覽器相容性的問題,算是比較常見的解法。

值得注意的是,如果你的 Server 端不支援 non-blocking IO 的話,他其實還是一般的 Polling

例如

(function polling() {
    $.ajax({
        url: "http://server",
        type: "post",
        dataType: "json",
        timeout: 30000,
        success: function(data) {
            /* Do something */
        },
        complete: function() {
            /* Polling here. */
            polling();
        }
    });
})();

在上面的程式碼中,等待三十秒後重複發送 AJAX 請求到 Server 端,而 Long Polling 的作法是

  • Client side 發送 Request 給 Server side
  • Server 收到後 Response 給 Client ,並斷開連線
  • Client 收到 Response 後,執行 Callback ,再次發送 Request 給 Sevrer

這樣的方式是無窮迴圈,但如果後端收到之後並沒有斷開連線,那麼前端就只會每 30 秒斷線重連,其實也就是一般的 Polling 而已。

非 non-blocking IO 的 Server 不行的原因:

假定送一個 AJAX 給 Server side, 事情做完之後,丟一個 Response 給 Client , 一樣會觸發 complete 條件。

但當你的 Server 沒放開連線,你只能等 Client timeout, 並且再次發送 Request 才能繼續動作,而這時候 Server 的資料到底有沒有完成,根本不知道,所以 non-blocking IO 的 Server 多少能避開這種問題。

但這都只是單向的溝通。

WebSocket

WebSocket 的誕生就是為了解決單向請求的問題,可以在一條連線上提供全雙工、雙向的資料傳輸,在這樣的標準下你可以很容易實作一個兼具可擴充性與即時性的網頁應用程式。

他的特點

  • 支援程度高,參考Can I use?
  • 建立於 TCP 協議之上,服務器端實現較容易
  • 與 HTTP 協議有良好的兼容性,默認端口也是 80 與 443 port,並且在握手階段(handshake)採用 HTTP 協議,因此不容易被屏蔽,能通過各種 HTTP 代理服務器
  • 性能較 Polling 好,通信高效

協議標示符號是 ws(若加密則為 wss),服務器網址就是 URL

ws://example.com:80/some/path

WebSocket 算是借用 HTTP 協議來完成一部分的 handshack

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

詳細更多部分請參考

參考資源