分布式架构 WebSocket 解决方案,学会了你就是那个架构师( 二 )


分布式缓存实现用户与客户端标识(FD)绑定关系大致做法为:

  1. 在服务启动时创建一个 全局唯一ID,保证多服务下这个 ID的唯一性,比如启动5个服务时,每个服务的ID都不能有相同,目的是用来分布式缓存的客户端FD标识所在的服务ID,当然 你也可以使用IP作为唯一性(可能会更直观点) 。
  2. 将 唯一ID_FD 作为哈希键存储,在某个事件或定时清除不活跃的哈希键 。要当前某个服务的所有哈希键的时候可以使用 hScan 循环迭代模糊匹配实现,必要时使用 hGetAll 获取所有哈希键值(并发高服务 在此提醒谨慎使用哈) 。
多节点服务器就会有分布式问题,解决分布式问题就找一个大家都能找到的地,比如说 MQTT、Kafka、RabbitMQ 等消息中间件,另外使用 Redis 的发布订阅(pubsub)功能 也一样可以实现,不过在此我选择的是用 RabbitMQ 来实现 。
改进后流程图如下:
负载均衡(SLB) 内所有服务启动时都绑定同一个RabbitMQ Fanout(广播模式) 交换机, 如果该交换机不存在则创建 。然后每个服务都生成一个唯一的该交换机队列(生成的交换机队列不能相同, 比如可以服务器1生成的队列名为 S1, 服务器2生成的队列名为 S2), 可以将生成的队列设置为 auto_delete: true, 这样就可以达到当 队列没有消费者的时候该队列会自动删除, 服务重启时又重新生成的效果 。接下来就是每个服务都注册该交换机队列的监听消费,当队列的每一条息出栈时都会广播到该交换机下的所有队列(即所有服务的队列监听事件都能收到PUSH进来的消息) 。客户端请求到 负载均衡(SLB) 任意一台服务器该服务器逻辑处理完后将要发送给客户端的消息推送至 RabbitMQ 消息队列消息队列将该消息广播到所有服务器的监听消费事件内所有服务器的监听消费事件内 Redis hScan 迭代遍历当前服务内所有客户端连接,取出所有符合用户ID对应的客户端标识(FD)进行推送消息 。(并发高时对 Redis 冲击很大,需要预估支撑力,对缓存哈希的读要求随并发高低而上升 O(n))

分布式架构 WebSocket 解决方案,学会了你就是那个架构师

文章插图
 
 
这种 WebSocket 分布式架构解决方案同时 实现了支持单个用户多设备、多平台同时在线的场景,不需要知道有多少台服务器(也就是说服务器可以无限动态扩容),不需要知道用户对应哪些服务器,也不需要知道各个服务器的IP地址,只需要处理各自服务器内的监听消费队列即可 。相对于一些通过搭建转发服务器、网关服务器等实现的 WebSocket 分布式架构 有着天然的优势,这些架构解决方案要复杂很多,特别是要实现多设备、多平台同时在线的场景时 更加、更加、更加复杂 。
 
生活不易,如果您觉得这篇文章写得不错就动动手指帮忙点个赞吧!感恩各位~




推荐阅读