浅谈分布式环境下 WebSocket
音讯共享问题
技术剖析
咱们在开发时会遇到须要应用即时通讯的场景,当然,实现形式很多,Socket
、MQTT
、Netty
…. 等等。
具体用哪种就在于业务的需要了,去抉择正当的形式实现。
明天小简要聊的场景便是分布式环境下,WebSocket
的音讯共享问题。
分布式环境下,业务方面往往最须要解决的是数据同步共享这类问题。
此时呈现了一个场景,后端存在一个分布式服务,我须要两个服务都能收到 WebSocket
的音讯,如何去实现?
或者说,服务端我的项目存在多个负载平衡实例,实例均在不同的实例上,这样当一次申请负载到 A 服务器实例时,socket
的 session
在 A 服务器线程上,第二次申请负载到另一台 B 服务器的实例,此时 B 服务器并不存在 A 服务器的 Session
(即Socket
的会话音讯)。
思考解决
思路一(失败)
咱们首先思考,改如何解决这个问题呢?要实现同步,依据下面的需要,咱们能够间接定位到 Socket 的 Session 不能共享问题,只有能够共享会话对象,那就能够解决以后问题。
没错,小简也是这样想的,然而,实际上是谬误的,请看下文。
咱们首先联想到,分布式下,咱们的分布式锁、分布式状态信息,都是能够通过 Redis
去实现一个共享的,那咱们间接给 Socket
的Session
通过 Redis
共享不就能够。
思路的确是对的,然而应用
Redis
共享对象是有条件的,要去实现Serializable
接口,才能够被序列化。
咱们查看源码就会发现,Socket
的 Session
是不能被序列化的,那天然不能去应用 Redis
来实现 Session
对象的共享了。
为什么 HttpSession
能够应用 Redis
共享?
/**
* @author JanYork
* @date 2023/3/14 11:36
*/
org.apache.catalina.session.StandardManager
org.apache.catalina.session.PersistentManager
WEB
的中的 HttpSession
次要是通过下面的两个管理器实现序列化的。
StandardManager
是 Tomcat
默认应用的,在 web
应用程序敞开时,对内存中的所有 HttpSession
对象进行长久化,把他们保留到文件系统中。
默认的存储文件为:<tomcat 装置目录 >/work/Catalina/< 主机名 >/< 应用程序名 >/sessions.ser
PersistentManager
比 StandardManager
更为灵便,只有某个设施提供了实现 org.apache.catalina.Store
接口的驱动类,PersistentManager
就能够将 HttpSession
对象保留到该设施。
所以 spring-session-redis
解决散布场景下的 session
共享就是将 session
序列化到 redis
中,应用 filter
加装璜器模式解决分布式场景 httpsession
享问题。
注:此段参考自程序员 DD 大佬的文章。
思路二
既然不能共享对象,那咱们共享音讯不就能够,咱们的目标是要其余实例也能够收到 Socket
的音讯,那咱们就是个 1
对n
的音讯模型,一对多音讯那就简略了。
哪些办法?
首先咱们会第一工夫想到,MQ
,也就是音讯队列中间件。
其次咱们也能够应用 Redis
的公布订阅性能实现。
MQ
应用 MQ
去实现一对多音讯,置信也不须要我多说,MQ
人造的播送、公布订阅、点对点、路由这些音讯模式能够很不便的解决这个问题。
Redis
Redis
实现有大佬曾经写过了,请参考:
如何应用
Redis
解决WebSocket
分布式场景下的Session
共享问题: https://cloud.tencent.com/developer/article/1955783
尾述
说浅谈就浅谈,文章就这么短(暗暗窃喜:又水一篇,嘿嘿),下篇再见。