Spring Boot系列21 Spring Websocket实现websocket集群方案讨论

栏目: Html5 · 发布时间: 6年前

内容简介:在上个博文上图中,用户A通过websocket注册到服务A,服务A通过STOMP协议订阅RabbitMQ上的消息,同理用户B。如果用户A连接到服务A上,那么在位于服务B上的MQ模块即使使用SimpMessagingTemplate实例向用户A发送消息,此消息也无法到达用户A,原因是因为服务B上没有服务A的注册信息,无法准确的推送消息.只有在服务A上的MQ模块使用SimpMessagingTemplate实例向这个用户发送消息,消息才会到达用户A针对这个问题下文我们通过3个方案解决这个问题,并详细分析每个方
Spring Boot系列21 Spring Websocket实现websocket集群方案讨论

在上个博文 Spring Boot系列20 Spring Websocket实现向指定的用户发送消息 中实现向指定用户发送消息的功能,但是我们将提供websocket服务的服务进行集群(如上图)则存在如下问题:

上图中,用户A通过websocket注册到服务A,服务A通过STOMP协议订阅RabbitMQ上的消息,同理用户B。如果用户A连接到服务A上,那么在位于服务B上的MQ模块即使使用SimpMessagingTemplate实例向用户A发送消息,此消息也无法到达用户A,原因是因为服务B上没有服务A的注册信息,无法准确的推送消息.只有在服务A上的MQ模块使用SimpMessagingTemplate实例向这个用户发送消息,消息才会到达用户A

针对这个问题下文我们通过3个方案解决这个问题,并详细分析每个方案的有缺点。

webSocket集群方案一

概述不管消息的接收者连接在哪个服务上,每个服务A/B都接收消息,对相同的消息都使用SimpMessagingTemplate实例进行推送,保证总有一个消息会被用户收到。

Spring Boot系列21 Spring Websocket实现websocket集群方案讨论

详细流程如下:

  1. 用户A/B分别通过ws连接服务A/B, 然后服务A/B通过stomp协议接入RabbitMQ
  2. 消息发送者将消息发送到RabbitMQ的交换机上,使用扇形交换机。这样保证同一个消息可以同时被服务A/B接收
  3. 两个服务上的MQ模块接收对应消息后,不管对应的用户是否是通过自己连接到RabbitMQ,直接使用SimpMessagingTemplate实例向消息中指定的用户推送消息
  4. 用户A/B接收到对应的消息

优点:

  1. 实现比较简单

不足:

  1. 消息生产者发送消息的RabbitMQ交换机必须是广播功能,如扇形交换机
  2. 为了保证消息顺利到达用户,相同的消息必须在两个服务A/B上执行相同的操作。这样如果服务越多,则重复的发送消息越多
  3. 如果用户不在线,无论发送多少消息用户都不能收到

webSocket集群方案二

概述使用 redis 缓存用户的websocket连接信息,记录用户登录到哪个服务上,当有消息过来时,将消息推送到用户登录的服务,然后服务都使用SimpMessagingTemplate实例进行推送

Spring Boot系列21 Spring Websocket实现websocket集群方案讨论

在方案一的基础上增加如下功能:

  1. 服务A/B上增加MQ模块,服务A/B上MQ模块会连接到RabbitMQ,分别订阅队列A/B
  2. 服务A/B增加WS模块,当websocket连接过来时,将此用户的连接信息存储到redis上,系统记住每个用户登录的到哪个服务
  3. 消息生产者将消息推送到交换机,不直接推送到服务A/B
  4. 增加新的模块dispatch,此模块接收到消息,然后从redis中读取要消息要推送到用户连接到那个服务器上,然后将消息发送到用户连接服务对应的队列中。如果消息要发送给用户B,则dispatch模块会将消息发送到队列B
  5. 服务A/B的MQ模块接收到消息后,使用SimpMessagingTemplate实例向指定用户推送消息

优点:

  1. 此方案克服上一个方案不足的地方

缺点

  1. 实现复杂
  2. 发送MQ消息的次数增加1倍

webSocket集群方案三

概述不使用SimpMessagingTemplate,使用RabbitMQ的客户端API直接向用户在RabbitMQ上订阅的队列发送消息

发现用户通过浏览器登录websocket并注册RabbitMQ时,此时这个连接会在RabbitMQ建立一个队列,队列的名称类似stomp-subscription-***,此队列绑定到默认交换机amq.topic,路由键为"web订阅队列名称+'-user'+websocket sessionId"(这里是demo-userpjplggbl,demo是stomp weboscket连接的队列名称,pjplggbl登录websocket登录时的websocket sessionId值),图片如下:

Spring Boot系列21 Spring Websocket实现websocket集群方案讨论

根据这个,设计如下架构:

Spring Boot系列21 Spring Websocket实现websocket集群方案讨论

在方案一的基础进行如下修改,新的架构图流程如下:

  1. 服务A增加WS模块,当websocket连接过来时,将此用户的连接信息(主要是websocket sesionId值)存储redis中
  2. 消息生产者发送消息到的交换机,这些服务不直接推送服务A/B
  3. 增加新的模块dispatch,此模块接收推送过来的信息,并从redis中读取消息接收用户对应的websocket sesionId值,然后根据上面的规则计算出用户对应的路由键,然后将消息发送到用户订阅的队列上
  4. 前端接收消息

优点:

  1. 即克服第一个方案不足的地方,又比第二个方案简单

结论

方案三是最好的方案,下一篇文章,我们会介绍如何在代码中实现方案三


以上所述就是小编给大家介绍的《Spring Boot系列21 Spring Websocket实现websocket集群方案讨论》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Kotlin程序员面试算法宝典

Kotlin程序员面试算法宝典

孙伟、楚秦 / 机械工业出版社 / 2018-12 / 69

本书是一本讲解程序员面试笔试算法的书籍。在写法上,除了讲解如何解答算法问题以外,还引入了例子辅以说明,以便读者能够更加容易地理解。 本书将程序员面试笔试过程中的各类算法类真题一网打尽。在题目的广度上,通过各种渠道,搜集了近3年来几乎所有IT企业面试笔试算法高频题目,所选择题目均为企业招聘使用题目;在题目的深度上,本书由浅入深、庖丁解牛式地分析每一个题目,并提炼归纳,同时,引入例子与源代码、时......一起来看看 《Kotlin程序员面试算法宝典》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试