站内通知调研

站内通知调研

项目需求

smpe-admin框架需要整合一个站内通知的模块,需求是能够实现后台用户间的消息通知,如管理员对普通用户的通知,以及系统消息的推送。

还需要满足后台定向给指定web登录用户推送消息,且可能同一账号会登录多个客户端都要接收到消息

消息推送目前常见的方法分为二类四种

  • HTTP Polling 客户端拉曳(Client Pull)
  • HTTP Long-Polling 客户端拉曳(Client Pull)
  • Server-Sent Events (SSE) 服务器推送(Server Push)
  • WebSocket 服务器推送(Server Push)

Server Push 和Client Pull 介绍

客户端拉曳(Client Pull)

​ 在客户端拖曳技术中,服务器发送一批数据,在HTTP响应或文档头标记中插入指令,让浏览器“在5秒内再次装入这些数据”或“10秒内前往某URL装入数据”。当指定的时间达到时,客户端就按照服务器的指·

服务器推送(Server Push)

推送技术的基础思想是将浏览器主动查询信息改为服务器主动发送信息。服务器发送一批数据,浏览器显示这些数据,同时保证与服务器的连接。当服务器需要再次发送一批数据时,浏览器显示数据并保持连接。以后,服务器仍然可以发送批量数据,浏览器继续显示数据,依次类推。

Server Push 和Client Pull 对比

在服务器推送技术中,HTTP 连接一直保持着,直到服务器知道自己已结束发送数据并发送一个结束信号,或者客户端中断连接。

而在客户端拖曳技术中,并不保持HTTP连接,相反,客户端被告知合时建立新连接,以及建立连接是获取什么数据。

在服务器推送中,奇妙之处在于“multipart/mixed”格式的MIME,它能够使一个HTTP响应包含许多数据项。

在客户端拖曳中,奇妙之处在于HTTP响应头标(或等效的HTML元素),它能告知客户端在指定的延时时间后执行何种动作。

客户端拖曳效率低,因为这必须每次为传送数据建立新的连接。但是它不必始终保持连接。

在实际情况中,建立HTTP连接通常需要花费相当多的时间,多达一秒甚至更多。

结论:

因此从性能上考虑,服务器推送对于最终用户更有吸引力,特别是对于需要经常更新信息的情况下。

四种技术对比

1. Polling 短轮询

是一种非常简单的实现方式。就是client通过定时任务不断的重复请求服务器,从而获取新消息,而server按时间顺序提供自上次请求以后发生的单个或多个消息。

Polling

优点

短轮询的优点非常明显,就是实现简单。当两个方向上的数据都非常少,并且请求间隔不是非常密集时,这种方法就会非常有效。例如,新闻评论信息可以每半分钟更新一次,这对用户来说是可以的。

缺点

它得缺点也是非常明显,一旦我们对数据实时性要求非常高时,为了保证消息的及时送达,请求间隔必须缩短,在这种情况下,会加剧服务器资源的浪费,降低服务的可用性。另一个缺点就是在消息的数量较少时,将会有大量的请求做无用功,进而也导致服务器资源的浪费。

2. Long-Polling 长轮询

客户端像传统轮询一样从服务端请求数据,服务端会阻塞请求不会立刻返回,直到有数据或超时才返回给客户端,然后关闭连接,客户端处理完响应信息后再向服务器发送新的请求。

大致步骤为:

  1. client向server请求并等待响应。
  2. 服务端将请求阻塞,并不断检查是否有新消息。如果在这个期间有新消息产生时就立即返回。否则一直等待至请求超时
  3. 当client 获取到新消息请求超时,进行消息处理并发起下一次请求。

Long Polling

优点

长轮询解决了频繁的网络请求浪费服务器资源可以及时返回给浏览器。

缺点

Long-Polling的缺点之一也是服务器资源的浪费,因为它和Polling的一样都属于被动获取,都需要不断的向服务器请求。在并发很高的情况下,对服务器性能是个严峻的考验。

以上两种方式都比较浪费服务器资源,不适合使用。

三、Server-sent Events(sse)

简介

sse与长轮询机制类似,区别是每个连接不只发送一个消息。客户端发送一个请求,服务端保持这个连接直到有新消息发送回客户端,仍然保持着连接,这样连接就可以消息的再次发送,由服务器单向发送给客户端。

原理

SSE本质是发送的不是一次性的数据包,而是一个数据流。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。

SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。

下面我们将通过一个下载文件的案例进行演示SSEWebSocket的消息推送,在这之前,我们先简单说一下我们项目的结构,整个项目基于SpringBoot 构建。

特点

SSE 是W3C定义的一组API规范,这使服务器能够通过HTTP将数据推送到Web页面,它具有如下特点:

  • 单向半双工:只能由server向client推送消息
  • 基于http:数据被编码为“text/event-stream”内容并使用HTTP流机制进行传输
  • 数据格式无限制:消息只是遵循规范定义的一组key-value格式&UTF-8编码的文本数据流,我们可以在消息payload 中可以使用JSON或者XML或自定义数据格式。
  • http 长连接: 消息的实际传递是通过一个长期存在的HTTP连接完成的,消耗资源更少
  • 简单易用的API

优点:

  • 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
  • 属于轻量级,使用简单;WebSocket 协议相对复杂。
  • 默认支持断线重连,WebSocket 需要自己实现。
  • 支持自定义发送的消息类型。

缺点:

  • 只能由服务端想客户端推送消息
  • SSE一般只传送文本,二进制数据需要编码后传送;Websocket默认支持二进制;

Server-Sent Events

浏览器支持情况:
support browser

Note:IE 浏览器可通过第三方JS库进行支持SSE

WebSocket

WebSocket 类似于标准的TCP连接,它是IETF(RFC 6455)定义的通过TCP进行实时全双工通信一种通信方式,这意味这它的功能更强大,常用于如股票报价器,聊天应用。

相比于SSE,它不仅可以双向通信,而且甚至还能处理音频/视频等二进制内容。

原理

WebSocket协议是借用HTTP协议的101 switchprotocol(服务器根据客户端的指定,将协议转换成为 Upgrade首部所列的协议)来达到协议转换的,从HTTP协议切换成WebSocket通信协议。

优点:

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

其他特点包括:

(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

缺点:

websocket 是长连接,受网络限制比较大,需要处理好重连,比如用户进电梯或电信用户打个电话网断了,这时候就需要重连,如果 ws 一直重连不上,有些较复杂的业务方会不愿意的。

websocket 很多坑,如果只是单页面还好,涉及到多页面,定时推送,复杂的推送,就非常容易出问题了,不管是前端,还是服务端都会遇到很多很多问题

一般有实时数据要求的会考虑 websocket

具体连接方式:

通过在请求头中增加 upgrade:websocket 及通信密钥(Sec-WebSocket-Key),使双方握手成功,建立全双工通信。

image-20210129154302429

(WebSocket客户端连接报文)

image-20210129154325524

(WebSocket服务端响应报文)

  • 通信过程:

websocket是纯事件驱动的,一旦 WebSocket 连接建立后,通过监听事件可以处理到来的数据和改变的连接状态。数据都以帧序列的形式传输。服务端发送数据后,消息和事件会异步到达。WebSocket编程遵循一个异步编程模型,只需要对WebSocket对象增加回调函数就可以监听事件。

image-20210129154704375

webSocket与sse的对比

1、协议:SSE是HTTP协议;Websocket是独立协议;

2、量级:SSE是轻量级;Websocket协议相对复杂;

3、断线:支持断线重连;Websocket需要自己实现;

4、数据格式:SSE一般只传送文本,二进制数据需要编码后传送;Websocket默认支持二进制;

5、SSE支持自定义发送的消息类型;

6、webSocket是全双工通道 sse是单向半双工

img

技术选择

如只需推送系统消息或用户之间推送消息,只需用轻量级的sse框架即可。

如需要实时通信则选用webSocket

一、需要解决的问题

如使用webSocket需要解决几个问题

  1. 断线重连和消息补发
  2. 离线消息问题
  3. 历史消息查询

1. 关于·webSocket掉线问题,网上找到了一篇博客可以解决

https://www.jianshu.com/p/5297732db7f2

但我们也需要防止断线的事情发生:

断线的可能原因1:websocket超时没有消息自动断开连接,应对措施:

这时候我们就需要知道服务端设置的超时时间是多少,在小于超时时间内发送心跳包,有2中方案,一种是客户端主动发送上行心跳包,另一种方案是服务端主动发送下行心跳包。下面主要讲一下客户端也就是前端如何实现心跳包:。

  1. 首先了解一下心跳包机制

    跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。

在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。

心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。

在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。

心跳检测步骤:
1客户端每隔一个时间间隔发生一个探测包给服务器
2客户端发包时启动一个超时定时器
3服务器端接收到检测包,应该回应一个包
4如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了

前端解决方案:

//心跳检测
var heartCheck = {
    timeout: 30000,        //30秒发一次心跳
    timeoutObj: null,
    serverTimeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
    },
    start: function(){
        var self = this;
        this.timeoutObj = setTimeout(function(){
            //这里发送一个心跳,后端收到后,返回一个心跳消息,
            //onmessage拿到返回的心跳就说明连接正常
            ws.send("ping");
            console.log("ping!")
            self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
                ws.close();     //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
            }, self.timeout)
        }, this.timeout)
    }
}

断线的可能原因2:websocket异常包括服务端出现中断,交互切屏等等客户端异常中断等等

针对这种异常的中断解决方案就是处理重连,下面我们给出的重连方案是使用js库处理:

引入reconnecting-websocket.min.js,ws建立链接方法使用js库api方法

2.离线消息问题我们可以采用webSocket+rabbitMQ

二、webSocket+rabbitMQ

RabbitMQ使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现(AMQP的主要特征是面向消息、队列、路由、可靠性、安全)。支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现很出色。

为什么选用rabbitMQ

优势:支持集群化、高可用部署架构、消息高可靠支持

复杂系统的解耦;

复杂链路的异步调用

瞬时高峰的削峰处理。

这里提一下RocketMQ,是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验、性能卓越、同时支持分布式事务等特殊场景。关键是它基于java开发,可以进行二次开发。

最重要的是Springboot对rabbitMq支持的很好

具体使用方式可以参考博客

https://blog.csdn.net/weixin_43617082/article/details/83780700

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值