乐趣区

关于后端:浅谈分布式环境下WebSocket消息共享问题

浅谈分布式环境下 WebSocket 音讯共享问题

技术剖析

咱们在开发时会遇到须要应用即时通讯的场景,当然,实现形式很多,SocketMQTTNetty…. 等等。

具体用哪种就在于业务的需要了,去抉择正当的形式实现。

明天小简要聊的场景便是分布式环境下,WebSocket的音讯共享问题。

分布式环境下,业务方面往往最须要解决的是数据同步共享这类问题。

此时呈现了一个场景,后端存在一个分布式服务,我须要两个服务都能收到 WebSocket 的音讯,如何去实现?

或者说,服务端我的项目存在多个负载平衡实例,实例均在不同的实例上,这样当一次申请负载到 A 服务器实例时,socketsession 在 A 服务器线程上,第二次申请负载到另一台 B 服务器的实例,此时 B 服务器并不存在 A 服务器的 Session(即Socket 的会话音讯)。

思考解决

思路一(失败)

咱们首先思考,改如何解决这个问题呢?要实现同步,依据下面的需要,咱们能够间接定位到 Socket 的 Session 不能共享问题,只有能够共享会话对象,那就能够解决以后问题。

没错,小简也是这样想的,然而,实际上是谬误的,请看下文。

咱们首先联想到,分布式下,咱们的分布式锁、分布式状态信息,都是能够通过 Redis 去实现一个共享的,那咱们间接给 SocketSession通过 Redis 共享不就能够。

思路的确是对的,然而应用 Redis 共享对象是有条件的,要去实现 Serializable 接口,才能够被序列化。

咱们查看源码就会发现,SocketSession 是不能被序列化的,那天然不能去应用 Redis 来实现 Session 对象的共享了。

为什么 HttpSession 能够应用 Redis 共享?
/**
 * @author JanYork
 * @date 2023/3/14 11:36
 */
org.apache.catalina.session.StandardManager
org.apache.catalina.session.PersistentManager

WEB的中的 HttpSession 次要是通过下面的两个管理器实现序列化的。

StandardManagerTomcat 默认应用的,在 web 应用程序敞开时,对内存中的所有 HttpSession 对象进行长久化,把他们保留到文件系统中。

默认的存储文件为:<tomcat 装置目录 >/work/Catalina/< 主机名 >/< 应用程序名 >/sessions.ser

PersistentManagerStandardManager 更为灵便,只有某个设施提供了实现 org.apache.catalina.Store 接口的驱动类,PersistentManager就能够将 HttpSession 对象保留到该设施。

所以 spring-session-redis 解决散布场景下的 session 共享就是将 session 序列化到 redis 中,应用 filter 加装璜器模式解决分布式场景 httpsession 享问题。

注:此段参考自程序员 DD 大佬的文章。

思路二

既然不能共享对象,那咱们共享音讯不就能够,咱们的目标是要其余实例也能够收到 Socket 的音讯,那咱们就是个 1n的音讯模型,一对多音讯那就简略了。

哪些办法?

首先咱们会第一工夫想到,MQ,也就是音讯队列中间件。

其次咱们也能够应用 Redis 的公布订阅性能实现。

MQ

应用 MQ 去实现一对多音讯,置信也不须要我多说,MQ人造的播送、公布订阅、点对点、路由这些音讯模式能够很不便的解决这个问题。

Redis

Redis实现有大佬曾经写过了,请参考:

如何应用 Redis 解决 WebSocket 分布式场景下的 Session 共享问题: https://cloud.tencent.com/developer/article/1955783

尾述

说浅谈就浅谈,文章就这么短(暗暗窃喜:又水一篇,嘿嘿),下篇再见。

退出移动版