2014-04-23 95 views
2

Web上處理WebSockets的大多數文章都是關於內存中的聊天。
我感興趣的是少一些即時聊天,這是持久的,就像博客的帖子的評論。WebSocket推送數據庫更新

我有兩個處理客戶端請求的服務器的集羣。
我不知道什麼是處理將數據庫更新推送到相應客戶端的最佳策略。

由於我使用Heroku來處理這個羣集(2個Web dynos),我顯然讀了this tutorial,目標是建立一個聊天室在所有客戶端之間共享。

它使用Redis來集中接下來的消息;每個服務器偵聽新消息通過websocket連接傳播到Web客戶端。

我的用例不同之處在於我有一個Neo4j數據庫,堅持每個客戶寫的每條消息。
我的目標是通知每個客戶從一個特定的房間,新的消息/評論剛剛被客戶持續。

通過與上面鏈接的教程類似的體系結構,我怎樣才能過濾僅傳播給用戶的新消息?有沒有簡單有效的方式來告訴Redis:

「(WebSocket說)當我的客戶端啓動websocket連接時,我會小心查詢所有持久消息並將它們發送到客戶端,但是我希望你(Redis)爲我提供所有新消息,我沒有發送給客戶,這樣我就能夠提供給他們。「

如何防止每次發生websocket連接時Redis發佈整個對話?這會導致重複,因爲數據庫查詢已經提供了現有的內容。

回答

1

這其實是一個相當常見的場景,在這裏你有三個組成部分:

  1. 的是保持開放的連接和所有客戶(負載平衡羣集,很明顯)無狀態的Web服務器
  2. A A集羣持久性主數據存儲 - Neo4j的你的情況
  3. 的消息發送/排隊用於廣播消息的後端穿過通道(因而跨服務器集羣) - Redis的

您的要求是新客戶可以實時接收最近消息的初始消息以及任何後續消息。所有這些都在您的連接處理程序中實現。

從本質上講,這是你的(僞)代碼應該是什麼樣子:

class ConnectionHandler: 

    redis = redis.get_connection() 

    def on_init(): 
     self.send("hello, here are all the recent messages") 
     recent_msgs = fetch_msgs_from_neo4j() 
     self.send(recent_msgs) 
     redis.add_listener(on_msg) 
     self.send("now listening on new messages") 

    def on_msg(msg): 
     self.send("new message: ") 
     self.send(msg) 

確切的實施真的取決於你的環境,但是這是事物的一般流程。

+0

但這些新事件會永久存儲在消息隊列中嗎?用戶第二次連接時,一旦啓動了監聽器,是不是會收到舊事件?這些在第一次「新」的舊事件。 – Mik378

+0

我不確定你在問什麼。如果您永久存儲這些消息,那麼是的,用戶將會收到它們,就像任何其他新用戶一樣。 –

+0

User1初始化websocket連接。正如你寫的,對Neo4j進行查詢是爲了檢索所有當前數據。假設它返回MessageA和MessageB。然後,爲了即時獲得下一條消息,訂閱了Redis頻道,以獲得未來的MessageC。 User1斷開連接然後重新連接。進程再次重新啓動:MessageA,B和C從Neo4j中檢索,但Redis也將返回MessageC(因爲之前在Redis中保留),導致MessageC的重複。我錯了嗎 ? – Mik378