開了N個知乎窗口,標題都有(1 條消息),點開其中一個窗口的消息提示後,(1 條消息)消失,緊接著其他所有標題都會陸續更新,什麼技術?

HTML5有一個websocket功能,對於低版本瀏覽器是如何做到的?類似於這種技術對於大訪問量時服務端的負載大嗎?

是否有好的主動從伺服器端『push』信息到客戶端的技術?


看了一下知乎的做法,是每個 tab 建立一個長連接,以便獲得伺服器端的事件然後更新。簡單來說,知乎讓瀏覽器發起一個請求,然後瀏覽器自然會等伺服器返回。伺服器有意不返回,僅在有事件推送時返回,或者 30 秒超時時返回,這樣瀏覽器就可以把返回理解為推送了。

知乎的做法並不是最有效率的,因為每個 tab 都建立了一個獨立的長連接,如果用戶打開很多個 tab 就會佔用很多伺服器資源。更理想的做法是如果 tab 之間能夠建立通信,則應該共享一個長連接。

P.S. 我以前在百度做網頁版的百度 Hi,所以比較了解所有這些長連接的做法。當年也研究過 Facebook Chat 的做法,就是多個 tab 共享一個長連接的。


我之前從沒有發現這個細節,看了題目後,便用chrome自帶的控制台,研究了一下。

我發現,知乎在打開頁面後,js一直在與伺服器交互(可能是一個定時請求),因為頁面沒有刷新,我猜是ajax,可能為了減小伺服器的壓力,所以基本每30s一次

打開具體的js,發現這個請求確實是為此。

我猜測,普通(server沒有新消息)30秒一次空回復。

一旦有新消息,馬上回復。因為有新消息的時候時間一般不是30s。


localStorage改變時有個事件會被觸發

這麼用:

window.addEventListener("storage",function(event){
},false);

demo:HTML5 Demo: Storage Events

或者不用storage事件只用localStorage也可以實現

每個頁面輪詢localStorage,只需要一個頁面發ajax


建議看下http://socket.io 機制

高瀏覽器用websocket , 低級瀏覽器自動降級為comet / ajax 輪詢

至於weibo為什麼不用,制約於技術選型(PHP,無demon , 無非同步)


低版本的瀏覽器,可以模仿一個長連接。

browser發起一個request,伺服器那邊去查有沒有新消息,沒有就暫時掛起該請求(不給回復),然後每隔一段時間y秒檢查一次,一旦有新消息,就finish這個request,一直沒有的話x分鐘後返回「無消息」的消息。

這樣的思路下,browser發起一個request,被伺服器掛起0-x分鐘,可以大大減少browser發起request的頻率,同時也能獲得近似於「即時」的回復(如果每30秒發起一個請求的話,消息延遲最大會是30秒)。

我們做的網站前面的x=2,y=5,有新消息更新到memcache,每次查新消息是去通過memcache查有沒有消息。看了一下知乎,它的x應該是30秒左右。伺服器那邊不知道是不是這樣做的。

一旦一個新消息被讀了,肯定會發送一個請求到伺服器,把這條消息,設置為已讀。其他打開的tab的掛起的請求就可以及時返回某某消息已讀,然後前台js做一些相應的設置。

這個方法應該可以兼容所有瀏覽器。


這應該是一種伺服器Push技術,可以看這篇文章:Comet:基於 HTTP 長連接的「伺服器推」技術

一般的伺服器Push技術包括:

  1. Ajax輪詢,每隔一段時間發送一個請求;
  2. HTTP長連接(利用Ajax等),伺服器Hold一段時間後再返回信息;
  3. HTTP Streaming,通過iframe和&標籤完成數據的傳輸;
  4. HTML5新引入的WebSocket,可以實現伺服器主動發送數據至網頁端。

很多基於Web頁面的即時消息都是利用這個技術實現的,包括人人網、新浪Weibo、Web QQ等在內都使用了這些方法。


我猜是長連接輪詢查詢是否有未讀的新消息,然後根據情況,JS設置標題


大家討論了那麼多技術,請問:

一個消息中有多個鏈接,請問如何知道用戶讀過此消息,然後需要設置已讀標記呢


可新浪微博的私信提醒, 到現在還沒有解決這個問題.


目前,國內網站,類似推送的效果,100%是ajax輪詢


推薦閱讀:

知乎長貼只有「更多」按鈕的瀏覽方式,是否影響帖子的易讀性?
新版新浪微博的個人首頁左側的「首頁」、「提到我的」、「評論」、「私信」、「收藏」等導航是如何做到局部刷新的?
傳送門:React Portal

TAG:前端開發 | JavaScript | Ajax | 知乎技術實現 | WebSocket |