Websocket(一)~ Spring Websocket Session共享解决思路

JSON 2017-07-03 16:18:51 70932

 Spring Websocket Session共享解决思路(背景)

在很久以前,我采用Nodejs 的方式,使用socket.io 实现了一把在线聊天。现在我需要实现一些功能,用户签到、抽奖还有抽奖、签到、任务信息完成播报等功能。

而这些任务完成,都要有一个特性,就是实时性,所以想用  Websocket  来尝试一下。接着就发现了一个问题,  Session共享  的问题。

在这里,我不得再次批判一下中国的互联网问题。百度的问题。

  1. 你搜索的未必是你想要的,一大堆标题党。
  2. 你搜索的10篇结果,可能10篇都是一样的。
  3. 爬虫、复制过来的比原创排名要好,如XX之家,推酷等恶瘤。

 Websocket Session 共享解决思路

好吧,言归正传。Websocket Session 共享?好多人想都不想,直接上来丢  Redis  、  Memcache  等等?常用的HttpSession 共享如下图

都是采用序列化和反序列化来实现,而Websocket Session  当你存储的时候会发现出现这样的问题。

java.io.NotSerializableException: org.springframework.web.socket.adapter.standard.StandardWebSocketSession

在知乎上看到讨论这个问题,摘抄一下。

 Websocket的长连接通道一但关闭了websocket session就失效了。不像http协议每次用就去新建一个连接。你是可以知道是哪个用户,也知道要发哪些数据,但是问题在于。连接关闭后你发不过去。这也是websocketsession不能序列化的原因。自己构建的session不能解决长连接的问题。

而我的观点。

我觉得 Websocket session 不能序列化的原因不应该在此,关闭失效,我们有失效调用的close方法,这个时候我从共享池(cache)中remove即可,只要cache里有,那么我就可以针对用户发送请求,而且还有一个很现实的问题,我几个节点运行的时候,轮询的时候,从A点切换到B点的时候,用户就不认识了。而且每个节点只知道每个节点的websocketSession,这设计太扯了。

事实证明我的观点还是有遗漏,问题出在,上面引用的描述,它不像Http协议每次用就去新建一个  Session  。而是前端  JS  创建  Websocket  创建链接,就一个Websocket Session 的生命周期开启。当一段时间不使用的时候,Websocket会主动关闭。如下图。

再次使用会出现“WebSocket is already in CLOSING or CLOSED state.” 。所以在再次使用的时候,需要重新开启一个Websocket Session ,而这个开启,是有前端 JS 来完成的。

所以这个处理很简单,需要增加判断,或者try...catch 来完成重新创建。

Websocket Session 共享解决(方案一)

既然Websocket Session 不能直接序列化然后存储,而且如果用户请求的时候,开始与集群中的A 节点创建链接,就算把这个  Session  拿到B 节点去再给用户Push 消息,应该也是不通(没测试)的。

所以我的解决方案采用订阅式队列去触发  Websocket  反推的方式来实现看上去是  Session共享  的,思路如下图:

Websocket Session  共享 思路图解释:

模块一:这里没有什么好说明的,因为每一个用户只创建以一个  Session  ,当用户再次链接到第二个节点的时候,第一个节点的  Session  就会关闭和销毁。而每个节点采用静态(static )的成员变量去存储(Map )当前节点的所有Websocket Session

模块二:因为每个节点存储的是每个节点的所有Websocket Session ,那么只需要判断下当前节点是否存在当前用户的Websocket Session ,存在则反推消息。

模块三:当有消息需要通过  Websocket  推送给对应的用户的时候,而又不知道这个用户在哪个节点,那么通过任务调度模块,把消息以订阅MQ 的方式放到  MQ  中,这样每个节点都可以收到消息,从而参照 “模块二” 判断当前用户是否存在当前节点。然后推送。

总结:目前我采用这种方式实现,没什么问题,但是是不是觉得太复杂了。是的,太重了,所以不推荐这样去解决。

Websocket Session 共享解决(方案二)

其实我们之所以要做共享,其实就是因为在集群环境中,在HA/Nginx等方案中,做轮询请求来减轻节点压力,这样导致用户可能分配在多个节点,那么如果我们采用IP等的Hash值规则,或者其他可以参考的规则。解决一个用户只会分配到一个节点上,那么就不存在Session共享了。这样的中间件好多。如我们的“伞神”提出的 采用阿里的 Tengine session sticky 组件” 就可以解决。其他的也很多。

我要吃饭了... ...


版权所属:SO JSON在线解析

原文地址:https://www.sojson.com/blog/238.html

转载时必须以链接形式注明原始出处及本声明。

本文主题:

如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。

关于作者
一个低调而闷骚的男人。
相关文章
Shiro教程(七)Shiro Session共享配置以及实现
HttpClient 多次请求session保持同Session
WebSocket Handshake failed due to invalid Upgrade header: null
Jsoup 提交参数乱码,解决思路解决过程及解决方案
SOJSON 拓展服务器被DDos攻击了晚上,是如何解决的?
Java模拟WSS websocket ssl请求,Java WSS模拟请求代码示例
IE、Firefox对同域名访问并发限制,及解决优化方案
神速ICP备案经验分,ICP备案居然天就通过了
DNS劫持,CDN和DNS劫持网络跳转,排查及解决经验分
Spring 3.x 升级到Spring 4.x 注意事项和步骤,错误解决方法
最新文章
PHP变量剖析 4
SQL全外连接剖析 119
SQL自然连接剖析 147
springboot启动原理 245
SQL右连接【RIGHT JOIN】详解及图解 450
SQL左链接【LEFT JOIN】详解及图解 357
SQL非等值连接剖析 262
SQL等链接剖析 291
SQL内连接详解及图解 385
python之numpy常用的100种数值相关方法及代码示例 231
最热文章
最新MyEclipse8.5注册码,有效期到2020年 (已经更新) 679205
苹果电脑Mac怎么恢复出厂系统?苹果系统怎么重装系统? 674561
免费天气API,全国天气 JSON API接口,可以获取五天的天气预报 599008
免费天气API,天气JSON API,不限次数获取十五天的天气预报 565146
Jackson 时间格式化,时间注解 @JsonFormat 用法、时差问题说明 551699
我为什么要选择RabbitMQ ,RabbitMQ简介,各种MQ选型对比 509186
Elasticsearch教程(四) elasticsearch head 插件安装和使用 479635
Jackson 美化输出JSON,优雅的输出JSON数据,格式化输出JSON数据... ... 262798
Java 信任所有SSL证书,HTTPS请求抛错,忽略证书请求完美解决 244092
Elasticsearch教程(一),全程直播(小白级别) 225115
支付扫码

所有赞助/开支都讲公开明细,用于网站维护:赞助名单查看

查看我的收藏

正在加载... ...