你来说说 websocket 有什么用?
双向通信,服务器端可以主动 push,给客户端发送通知。我想着,这还是较为简单的
那websocket多个节点有什么问题?
头条面试官的提问让我的回忆飘到了一个下午,想起了我两个同事之间的对话
引子
咱有部分用户收不到通知了
通知是由ws服务控制的,它最近是有啥改动么
也没改啥,以前单个节点也没有问题
想起来了,接上面通知,把服务都从单节点改成了多节点
对,说是为了什么 HA,两位数用户的服务需要折腾吗
没事,这样出去了也有搭建高可用服务与 websocket 负载均衡的经验了
说的倒也是!不过这样确实会有 ws 分布式的问题
简单,加个 reids 就好了
多节点问题
在开始思考分布式会有什么问题时,先来回答一个问题: 服务端如何与客户端主动PUSH?
在 ws 服务端,当与客户端连接成功后,会生成一个对象 connection
,ws 会维护一个与客户端所有连接的 connections
。如果想要主动推送消息到客户端,只需要调用API connection.sendText(message)
。
那如何给所有人广播消息呢?
服务器只需要与它自身的所有连接 server.connections
挨个发消息就是广播,所以它只是一个伪广播:我要给群里所有人发消息,但我不能在群里发,只能挨个私发。
单节点
当单节点时所有用户都能正常收到通知,流程如下
ws 单节点时
这时所有用户都能收到消息通知
多节点
当多节点时,就会有部分用户无法正常收到通知,从以下流程图中可以很清楚地看到问题所在
ws 多节点时
负载到节点2的所有用户都没有收到消息通知
如何解决
多节点服务器就会有分布式问题,解决分布式问题就找一个大家都能找到的地,比如说 Redis
,比如说 Kafka
等消息件
改进后流程图如下
- 请求 websocket 服务,向所有用户推送消息
- 负载均衡到某个节点
- 该节点向 redis/kafka 推送该消息
- 所有节点在 redis/kafka 上订阅到该消息
- 订阅成功后所有节点向客户端 push 消息
借用 redis
redis PUBSUB
其中有一个细节是 pub/sub 那里,redis 的 pubsub
较 Kafka
等消息中间件更为轻便,最主要的是与ws集成的社区方案比较成熟,这点很重要,如 Node 中的以下两个
- graphql subscriptions – redis
- socket.io-redis
pubsub
在 redis 中的命令如下
- pub:
publish channel message
- sub:
subscribe
如果我们要订阅 eat
这个 channel
的话,图示如下
redis pubsub example
进一步追问
面试官见我回答完问题后,又一次追问
那 websocket 如何向特定的用户组推送消息?
假如一个学校有以下数据结构
Class
: 代表班级Student
: 代表学生,每个学生都在其中一个班级
那假如要向 Class:201901
班级的所有学生发送通知,应该如何实现
欢迎在 Issue 中讨论: 【Q029】websocket 如何向特定用户组推送消息
小结
借用解决方案的图作为小结
借用 redis
最后,面试结束,头条的面试官很满意,问,你有什么问题要问我吗
我问道,那可以点个赞吗
如果你对全栈面试,前端工程化,graphql,devops,个人服务器运维以及微服务感兴趣的话,可以关注我
原文链接:https://blog.51cto.com/u_15077548/2608961
原创文章,作者:优速盾-小U,如若转载,请注明出处:https://www.cdnb.net/bbs/archives/7190