本文對websocket集羣的方案進行討論:前端
在上個博文Spring Boot系列20 Spring Websocket實現向指定的用戶發送消息中實現向指定用戶發送消息的功能,可是咱們將提供websocket服務的服務進行集羣(如上圖)則存在以下問題:web
上圖中,用戶A經過websocket註冊到服務A,服務A經過STOMP協議訂閱RabbitMQ上的消息,同理用戶B。若是用戶A鏈接到服務A上,那麼在位於服務B上的MQ模塊即便使用SimpMessagingTemplate實例向用戶A發送消息,此消息也沒法到達用戶A,緣由是由於服務B上沒有服務A的註冊信息,沒法準確的推送消息.只有在服務A上的MQ模塊使用SimpMessagingTemplate實例向這個用戶發送消息,消息纔會到達用戶Aredis
針對這個問題下文咱們經過3個方案解決這個問題,並詳細分析每一個方案的有缺點。後端
概述 無論消息的接收者鏈接在哪一個服務上,每一個服務A/B都接收消息,對相同的消息都使用SimpMessagingTemplate實例進行推送,保證總有一個消息會被用戶收到。 瀏覽器
詳細流程以下:緩存
優勢:服務器
不足:websocket
概述 使用redis緩存用戶的websocket鏈接信息,記錄用戶登陸到哪一個服務上,當有消息過來時,將消息推送到用戶登陸的服務,而後服務都使用SimpMessagingTemplate實例進行推送session
在方案一的基礎上增長以下功能:架構
優勢:
缺點
概述 不使用SimpMessagingTemplate,使用RabbitMQ的客戶端API直接向用戶在RabbitMQ上訂閱的隊列發送消息
發現用戶經過瀏覽器登陸websocket並註冊RabbitMQ時,此時這個鏈接會在RabbitMQ創建一個隊列,隊列的名稱相似stomp-subscription-***,此隊列綁定到默認交換機amq.topic,路由鍵爲"web訂閱隊列名稱+'-user'+websocket sessionId"(這裏是demo-userpjplggbl,demo是stomp weboscket鏈接的隊列名稱,pjplggbl登陸websocket登陸時的websocket sessionId值),圖片以下:
根據這個,設計以下架構:
在方案一的基礎進行以下修改,新的架構圖流程以下:
優勢:
方案三是最好的方案,下一篇文章,咱們會介紹如何在代碼中實現方案三