最近在项目中在做一个消息推送的功能,比如客户下单之后通知给给对应的客户发送系统通知,这种消息推送需要使用到全双工的websocket
推送消息 。
所谓的全双工表示客户端和服务端都能向对方发送消息 。不使用同样是全双工的上一篇文章Spring Boot 整合单机websocket介绍了http
是因为http
只能由客户端主动发起请求,服务接收后返回消息 。websocket
建立起连接之后,客户端和服务端都能主动向对方发送消息 。
websocket
在单机模式下进行消息的发送和接收:文章插图
用户A
和用户B
和web
服务器建立连接之后,用户A
发送一条消息到服务器 , 服务器再推送给用户B
,在单机系统上所有的用户都和同一个服务器建立连接,所有的session
都存储在同一个服务器中 。单个服务器是无法支撑几万人同时连接同一个服务器,需要使用到分布式或者集群将请求连接负载均衡到到不同的服务下 。消息的发送方和接收方在同一个服务器,这就和单体服务器类似,能成功接收到消息:
文章插图
但负载均衡使用轮询的算法,无法保证消息发送方和接收方处于同一个服务器,当发送方和接收方不是在同一个服务器时,接收方是无法接受到消息的:
文章插图
websocket集群问题解决思路客户端和服务端每次建立连接时候,会创建有状态的会话
session
,服务器的保存维持连接的session
。客户端每次只能和集群服务器其中的一个服务器连接,后续也是和该服务器进行数据传输 。要解决集群的问题,应该考虑
session共享
的问题,客户端成功连接服务器之后,其他服务器也知道客户端连接成功 。方案一:session 共享(不可行)和
websocket
类似的http
是如何解决集群问题的?解决方案之一就是共享session
, 客户端登录服务端之后,将session
信息存储在Redis
数据库中,连接其他服务器时,从Redis
获取session
, 实际就是将session
信息存储在Redis
中,实现redis的共享 。session
可以被共享的前提是可以被序列化,而websocket
的session
是无法被序列化的,http
的session
记录的是请求的数据,而websocket
的session
对应的是连接,连接到不同的服务器,session
也不同 , 无法被序列化 。方案二:ip hash(不可行)
http
不使用session
共享,就可以使用Nginx
负载均衡的ip hash
算法,客户端每次都是请求同一个服务器,客户端的session
都保存在服务器上,而后续请求都是请求该服务器,都能获取到session
, 就不存在分布式session
问题了 。websocket
相对http
来说,可以由服务端主动推动消息给客户端,如果接收消息的服务端和发送消息消息的服务端不是同一个服务端,发送消息的服务端无法找到接收消息对应的session
,即两个session不处于同一个服务端,也就无法推送消息 。如下图所示:文章插图
解决问题的方法是将所有消息的发送方和接收方都处于同一个服务器下,而消息发送方和接收方都是不确定的,显然是无法实现的 。方案三:广播模式将消息的发送方和接收方都处于同一个服务器下才能发送消息,那么可以转换一下思路,可以将消息以消息广播的方式通知给所有的服务器,可以使用消息中间件发布订阅模式,消息脱离了服务器的限制,通过发送到中间件,再发送给订阅的服务器,类似广播一样,只要订阅了消息,都能接收到消息的通知:
文章插图
发布者发布消息到消息中间件,消息中间件再将发送给所有订阅者:
文章插图
广播模式的实现搭建单机 websocket参考以前写的websocket单机搭建 文章,先搭建单机
推荐阅读
- 从0到1搭建redis6.0.7
- 京东云开发者|mysql基于binlake同步ES积压解决方案
- 关于ASP.NET Core WebSocket实现集群的思考
- 京东云开发者|IoT运维 - 如何部署一套高可用K8S集群
- 十六 企业级自定义表单引擎解决方案--Excel导入导出
- 一台虚拟机,基于docker搭建大数据HDP集群
- 5 why 分析法,一种用于归纳抽象出解决方案的好方法
- 【多服务场景化解决方案】AR虚拟技术助力智能家装
- 二 Istio:在Kubernetes(k8s)集群上安装部署istio1.14
- three.js webgl3D光伏,3D太阳能能源,3D智慧光伏、光伏发电、清洁能源三维可视化解决方案——第十六课