本文对websocket集群的方案进行讨论:前端
在上个博文Spring Boot系列20 Spring Websocket实现向指定的用户发送消息中实现向指定用户发送消息的功能,可是咱们将提供websocket服务的服务进行集群(如上图)则存在以下问题:web
上图中,用户A经过websocket注册到服务A,服务A经过STOMP协议订阅RabbitMQ上的消息,同理用户B。若是用户A链接到服务A上,那么在位于服务B上的MQ模块即便使用SimpMessagingTemplate实例向用户A发送消息,此消息也没法到达用户A,缘由是由于服务B上没有服务A的注册信息,没法准确的推送消息.只有在服务A上的MQ模块使用SimpMessagingTemplate实例向这个用户发送消息,消息才会到达用户Aredis
针对这个问题下文咱们经过3个方案解决这个问题,并详细分析每一个方案的有缺点。后端
概述 无论消息的接收者链接在哪一个服务上,每一个服务A/B都接收消息,对相同的消息都使用SimpMessagingTemplate实例进行推送,保证总有一个消息会被用户收到。 浏览器
详细流程以下:缓存
优势:服务器
不足:websocket
概述 使用redis缓存用户的websocket链接信息,记录用户登陆到哪一个服务上,当有消息过来时,将消息推送到用户登陆的服务,而后服务都使用SimpMessagingTemplate实例进行推送session
在方案一的基础上增长以下功能:架构
优势:
缺点
概述 不使用SimpMessagingTemplate,使用RabbitMQ的客户端API直接向用户在RabbitMQ上订阅的队列发送消息
发现用户经过浏览器登陆websocket并注册RabbitMQ时,此时这个链接会在RabbitMQ创建一个队列,队列的名称相似stomp-subscription-***,此队列绑定到默认交换机amq.topic,路由键为"web订阅队列名称+'-user'+websocket sessionId"(这里是demo-userpjplggbl,demo是stomp weboscket链接的队列名称,pjplggbl登陆websocket登陆时的websocket sessionId值),图片以下:
根据这个,设计以下架构:
在方案一的基础进行以下修改,新的架构图流程以下:
优势:
方案三是最好的方案,下一篇文章,咱们会介绍如何在代码中实现方案三