2012-06-20 36 views
2

所以我讀過一些關於擴展Socket.IO的文章。出於各種原因,我不想使用內置的Socket.IO擴展機制(大多數情況下它效率低下,因爲它從我的角度出發,向Redis發佈了更多的東西)。Redis客戶端廣播問題(在Socket.IO中)

所以我想出了這個簡單的想法:

每個Socket.IO服務器創建的Redis的pub/sub /存儲的客戶端,連接到Redis的和訂閱的頻道。現在,當我想要廣播數據時,我只需將它發佈到Redis,然後所有其他Socket.IO服務器就可以獲得它並將其推送給用戶。

雖然有一個問題(我認爲這也是Socket.IO內置機制的問題)。假設我想知道所有連接用戶的數量。至少有兩種方式:

  1. 服務器A向Redis發佈give_me_clients。然後,每個Socket.IO服務器統計連接數併發布number_of_clients。服務器A抓取這些數據,將其合併併發送給客戶端。

  2. 每當用戶連接/斷開連接到服務器時,每個服務器都會在Redis中更新number_of_clients_for::ID_HERE。然後,服務器A僅提取數據並將其合併。可能會更有效率。

有這些解決方案雖然問題:

  1. 服務器A不知道其他的服務器。所以他不知道他應該什麼時候停止收聽number_of_clients。可以通過使服務器A知道其他服務器來解決它:只要服務器連接到Redis,他就會發布new_server(服務器A獲取數據並將其存儲在內存中)。但是,當Redis - Socket.IO連接中斷時該怎麼辦? Redis有辦法通知客戶端某個客戶端已斷開連接嗎?

  2. 其實和上面一樣。當Socket.IO服務器崩潰時如何清除number_of_clients數據?

所以真正的問題是:Redis可以通知(發佈到chanel)客戶端,其中一個連接剛剛結束?

回答

2

經過大量測試後,似乎Redis沒有這樣的功能。另外我發現,縮放Socket.IO真的很痛苦。

所以我從Socket.IO切換到WS(請參閱this link)。它是低級的(但對我來說是完美的),它只支持WebSockets(所有主要版本)。但後來我只想支持WebSocket和FlashSocket(我必須手動輸入,但這很好)。

好處是我可以很容易地創建這樣的服務器集羣。 HAProxy幾乎可以與這些服務器一起使用(一些小調整)。服務器可以在本地網絡上輕鬆通信(如果羣集很大,則使用UDP或中央TCP服務器)。

缺點是人們必須手動實現一些很酷的功能,比如心跳,廣播,房間等等。你也想要長時間投票回退,但在我的情況下這很好。縮放比較重要,恕我直言。

+0

我已經切換到ws,我基本上運行一個process.on退出並通過'wss.clients'循環並刪除我的redis存儲中的所有'user:ids'(如果服務器失敗)。我遇到的一個簡單問題是私人消息傳遞。如果我在端口9300和9301上有2個ws服務器,並且來自9301的用戶想要發送消息給9300中的用戶(或者可能是任何其他服務器/端口),我不知道如何讓其他用戶知道。我是否只將私人消息請求發佈到redis服務器,並找出用戶正在向其發送消息的wss服務器? –

+1

@NiCkNewman我認爲,對於每個用戶,您應該瞭解該用戶在哪個服務器上(在像Redis這樣的共享位置)。然後,您只需檢索該信息並直接向目標服務器發送消息。但最有效的方法是通過用戶意識到他的朋友在哪個服務器上並直接將消息發送到該服務器。 – freakish

+0

當然,所有這些都取決於上下文。例如,您可能想保留聊天記錄(例如Facebook),然後它變得更加複雜。我沒有太多的聊天服務器經驗,所以我不想把你引向錯誤的方向。 :( – freakish