iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0

前言

昨天我們完成了用 WebSocket 將站內信通知推送給客戶端的用戶,流程大致上是用戶打開我們的應用時,觸發了一個 WebSocket 連接請求到後端,後端 ws//: 收到請求後也回應了,於是這個協議升級的動作就完成,前後端就建立起了 WebSocket 的連接,這個連接的狀態會一直保存在後端服務器,只要這個狀態一直都 isOpen 就可持續通信,但問題就來了,萬一我們現在因為用戶流量增加,需要為我們的 Server 實例做水平擴展,假設跟用戶取得連接的是 Server A,但處理推送的是 Server B,這樣 Server B 沒有跟用戶連接的狀態啊,這樣怎麼搞?所以這時就有必要引入 Redis Pub/Sub 來保存分布式環境下 WebSocket 的狀態了。

什麼是 Redis Pub/Sub?

Redis Pub/Sub 是一個訂閱發布的模式,它可以在發布者不知道訂閱的人是誰的情況下發送消息,訂閱者自己會訂閱 Channel 來接收,這種模式實現訂閱發布消息的解耦。這個模式有以下幾個特性:

  1. 即時性:消息一發布就立即傳遞給所有訂閱者。延遲在毫秒級別,適合即時通知的場景。沒有持久化,專注實時性。
  2. 輕量級通信:消息結構簡單,傳遞開銷極小。適合高頻的狀態同步和簡單指令傳遞。記憶體佔用低,不會累積歷史消息。
  3. 動態訂閱機制:支持運行時動態訂閱與取消。支持模式匹配,ex: user:* 匹配所有用戶相關 Channel。天然支持一對多和多對多消息廣播。

那它在我們的系統裡要幹嘛?

  1. 實例間狀態同步:用戶在 Server A 上線,需要告知其他 Server 這個狀態變化。下線要清空所有實例的相關紀錄。確保每個實例都有完整用戶分布的情報。
  2. 跨實例消息路由:推送時先確認用戶狀態在哪裡,如果在其他地方,通過 Redis 發送推送指令給目標實例。智能消息路由。
  3. 實時事件廣播:系統級事件的即時通知。

與 Kafka 的混用策略

Kafka 也是 Pub/Sub 模式但它主要負責擔任的是業務邏輯的載體,是真正出貨的工廠,Redis 比較像分流的角色,分到對應的 WebSocket 推送器。Kafka 的消息是持久化且有序的,還有重試的機制,這對業務邏輯來說很重要,所以 Kafka 負責裝真正的業務消息,Redis Pub/Sub 裝輕量的通知路由消息。但為何不能擇一就好?因為 Kafka 延遲時間比較長,又更適合做批量、高吞吐的工作,資源消耗大,送一些小東西大才小用,而 Redis Pub/Sub 如果裝業務邏輯的消息,它又沒持久化,消息丟了就沒了,也沒消息確認機制,無法保證消息被正確處理,不適合處理負責業務邏輯跟大量數據。

話說為何要用 Redis Pub/Sub 而不是直接把 WebSocket Session 放到 Redis 裡,要推送的實例自己去 Redis 取用呢?因為 WebSocket Session 是不可序列化的 JVM 實例,它有本地性,無法存到 Redis 給其他實例使用,所以它只會傳遞推送的命令,由保有該連接的實例收到命令後推送出去。

總結

今天先把一些理論前導一下就好,明天再開始實作基礎的配置跟簡單測試:

  1. Redis Pub/Sub 基礎配置
  2. DistributedSessionManager 核心實作
  3. 推送通知功能整合
  4. 多實例測試驗證

上一篇
Day 17 | 發送站內信並用 WebSocket 直接推送通知給用戶
下一篇
Day 19 | Redis Pub/Sub 分布式 WebSocket 實作:從配置到核心功能完整實現
系列文
系統設計一招一式:最基本的功練到爛熟就是殺手鐧,從單體架構到分布式系統的 Lab 實作筆記19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言