本文公众号来源:Rude3Knife
作者:蛮三刀把刀
前言
书接上文,我们开始对我们的小小聊天室进行集群化改造。
本文内容摘要:
为何要改造为分布式集群
如何改造为分布式集群
用户在聊天室集群如何发消息
用户在聊天室集群如何接收消息
补充知识点:STOMP 简介
功能一:向聊天室集群中的全体用户发消息——Redis的订阅/发布
功能二:集群集群用户上下线通知——Redis订阅发布
功能三:集群用户信息维护——Redis集合
WebSocket集群还有哪些可能性
本文源码:(妈妈再也不用担心我无法复现文章代码啦)
https://github.com/qqxx6661/springboot-websocket-demo/releases/tag/%E9%9B%86%E7%BE%A4%E7%89%88
正文
WebSocket集群/分布式改造:实现多人在线聊天室
为何要改造为分布式集群
分布式就是为了解决单点故障问题,想象一下,如果一个服务器承载了1000个大佬同时聊天,服务器突然挂了,1000个大佬瞬间全部掉线,大概明天你就被大佬们吊起来打了。
当聊天室改为集群后,就算服务器A挂了,服务器B上聊天的大佬们还可以愉快的聊天,并且在前端还能通过代码,让连接A的大佬们快速重连至存活的服务器B,继续和大家愉快的聊天,岂不美哉!
总结一下:实现了分布式WebSocket后,我们可以将流量负载均衡到不同的服务器上并提供一种通信机制让各个服务器能进行消息同步(不然用户A连上服务器A,用户B脸上服务器B,它们发消息的时候对方都没法收到)。
如何改造为分布式集群
当我们要实现分布式的时候,我们则需要在各个机器上共享这些信息,所以我们需要一个Publish/Subscribe的中间件。我们现在使用Redis作为我们的解决方案。
1. 用户在聊天室集群如何发消息
假设我们的聊天室集群有服务器A和B,用户Alice连接在A上,Bob连接在B上、
Alice向聊天室的服务器A发送消息,A服务器必须要将收到的消息转发到Redis,才能保证聊天室集群的所有服务器(也就是A和B)能够拿到消息。否则,只有Alice在的服务器A能够读到消息,用户Bob在的服务器B并不能收到消息,A和B也就无法聊天了。
2. 用户在聊天室集群如何接收消息
说完了发送消息,那么如何保证Alice发的消息,其他所有人都能收到呢,前面我们知道了Alice发送的消息已经被传到了Redis的频道,那么所有服务器都必须订阅这个Redis频道,然后把这个频道的消息转发到自己的用户那里,这样自己服务器所管辖的用户就能收到消息。
补充知识点:STOMP 简介
上期我们搭建了个websocket聊天室demo,并且使用了STOMP协议,但是我并没有介绍到底什么是STOMP协议,同学们会有疑惑,这里对于STOMP有很好地总结:
当直接使用WebSocket时(或SockJS)就很类似于使用TCP套接字来编写Web应用。因为没有高层级的线路协议(wire protocol),因此就需要我们定义应用之间所发送消息的语义,还需要确保连接的两端都能遵循这些语义。
就像HTTP在TCP套接字之上添加了请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式(frame-based wire format)层,用来定义消息的语义。
与HTTP请求和响应类似,STOMP帧由命令、一个或多个头信息以及负载所组成。例如,如下就是发送数据的一个STOMP帧:
>>> SEND
transaction:tx-0
destination:/app/marco
content-length:20
{"message":"Marco!"}
好了,介绍完了概念,让我们开始动手改造!
功能一:向聊天室集群中的全体用户发消息——Redis的订阅/发布
如果你不熟悉Redis的sub/pub(订阅/发布)功能,请看这里进行简单了解它的用法,很简单:
https://redisbook.readthedocs.io/en/latest/feature/pubsub.html
在我们上篇文章的Demo基础上,我们进行集群改造。上一篇文章的源码见下方:
https://github.com/qqxx6661/springboot-websocket-demo/releases/tag/%E5%8D%95%E6%9C%BA%E7%89%88
1. 添加Redis依赖pom
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
2. application.properties新增redis配置
当然首先要确保你安装了Redis,windows下安装redis比较麻烦,你可以搜索redis-for-windows下载安装。
# redis 连接配置
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.password=
spring.redis.port=6379
spring.redis.ssl=false
# 空闲连接最大数
spring.redis.jedis.pool.max-idle=10
# 获取连接最大等待时间(s)
spring.redis.jedis.pool.max-wait=60000
3. 在application.properties添加频道名定义
# Redis定义
r