你來說說 websocket 有什麼用
雙向通信,服務器端可以主動 push,給客戶端發送通知
那websocket多個節點有什麼問題?
頭條面試官的提問讓我的回憶飄到了一個下午,想起了我兩個同事之間的對話
引子
咱有部分用戶收不到通知了
通知是由ws服務控制的,它最近是有啥改動麼
也沒改啥,以前單個節點也沒有問題
想起來了,接上面通知,把服務都從單節點改成了多節點
對,說是為了什麼 HA,兩位數用戶的服務需要折騰嗎
沒事,這樣出去了也有搭建高可用服務與 websocket 負載均衡的經驗了
說的倒也是!不過這樣確實會有 ws 分佈式的問題
簡單,加個 reids 就好了
多節點問題
在開始思考分佈式會有什麼問題時,先來回答一個問題: 服務端如何與客戶端交流?
在 ws 服務端,當與客戶端連接成功後,會生成一個對象 connection ,ws 會維護一個與客戶端所有連接的 connections 。如果想要主動推送消息到客戶端,只需要調用API connection.sendText(message) 。
那如何給所有人廣播消息呢?
服務器只需要與它自身的所有連接 server.connections 挨個發消息就是廣播,所以它只是一個偽廣播:我要給群裡所有人發消息,但我不能在群裡發,只能挨個私發。
單節點
當單節點時所有用戶都能正常受到通知,流程如下

這時所有用戶都能收到消息通知
多節點
當多節點時,就會有部分用戶無法正常受到通知,從以下流程圖中可以很清楚地看到問題所在

負載到節點2的所有用戶都沒有收到消息通知
如何解決
多節點服務器就會有分佈式問題,解決分佈式問題就找一個大家都能找到的地,比如說 Redis,比如說 Kafka 等消息件
改進後流程圖如下
- 需要向所有用戶推送消息,請求 websocket 服務
- 負載均衡到某個節點
- 該節點向 redis/kafka 推送消息: 向所有用戶推送消息通知
- 所有節點在 redis/kafka 上訂閱消息
- 訂閱成功後所有節點向客戶端 push 消息
redis PUBSUB
其中有一個細節是 pub/sub 那裡,redis 的 pubsub 較 Kafka 等消息中間件更為輕便, 最主要的是與ws集成的社區方案比較成熟,這點很重要 ,如 Node 中的以下兩個
- graphql subscriptions - redis
- socket.io-redis
pubsub 在 redis 中的命令如下
publish channel message
subscribe
如果我們要訂閱 eat 這個 channel 的話,圖示如下
小結
借用解決方案的圖作為小結
閱讀更多 Java高級技術架構 的文章