1、什么叫做消息推送
传统互联网上数据交互一般有poll和push两种方式。
- poll典型使用场景是浏览网页,是用户主动发起请求,向服务器获取数据;
- push刚好相反,通过服务器直接发送数据给客户端,用户被动接受消息,类似于更加及时的短信。
PUSH是互联网上内容提供者和内容定制方之间的一种通信机制,利用在服务器端的程序把数据源源不断地推向客户端,大大提高客户机和服务器之间的交互性能。
2、有哪些可以实现web消息推送的技术
短轮询(polling)
- 怎么做?
- 前端定期、高频的隔一段时间就去查询服务器有没有新消息
- 服务器接到请求后,如果有新消息就会将新消息返回给客户端,如果没有新消息就返回空列表,并关闭连接。
- 优点:服务端逻辑简单;
- 缺点:
- 为了提升实时性,短轮询的频率一般比较高,但大部分轮询请求实际上是无用的,客户端即费电也费流量。
- 高频请求对服务端资源的压力比较大,一是大量服务器用于扛高频轮询的QPS(每秒查询率),二是对后端存储资源也有较大压力。
- 应用:并发用户量少,而且要求消息地实时性不高,一般很少采用
长轮询(long-polling)
- 过程:
- 客户端向服务器发送Ajax请求
- 服务器将请求挂起[不返回响应],直到有新消息或者超时,异常才返回消息并关闭连接
- 客户端处理完响应消息之后再向服务器发送新地请求 。
- 为了节约资源,一次长轮询的周期时间最好在 10s ~ 25s左右
- 可以看出,相比于短轮询,它的改进在于:
- 短轮询模式下,服务端不管本轮有没有新消息产生,都会马上响应并返回。
- 长轮询模式下,当本次请求没有获取到新消息时,并不会马上结束返回,而是在服务端“悬挂(hang)”,等待一段时间;如果在等待的这段时间内有新消息产生,就能马上响应返回。
- 优点:
- 实时性高,无消息的情况下不会进行频繁的请求;[数据更新后,可以立即推送,仅在数据更新时,才有推送]
- 能大幅降低短轮询模式中客户端高频无用的轮询导致的网络开销和功耗开销,也降低了服务端处理请求的QPS
- 缺点:长轮询并没有完全解决服务端资源高负载的问题
- 服务端悬挂(hang)住请求,只是降低了入口请求的QPS,并没有减少对后端资源轮询的压力。假如有1000个请求在等待消息,可能意味着有1000个线程在不断轮询消息存储资源
- 长轮询在超时时间内没有获取到消息,会结束返回,因此仍然没有完全解决客户端“无效”请求的问题
- 使用场景:
- 对实时性要求比较高,但是整体用户量不太大。
- 它在不支持websocket的浏览器段的场景下还是有比较多的使用。
- 长轮询实现:
- 客户端发起一个请求,服务端通常是在200ms内返回结果,但长轮询的话,是有消息才立马返回;
- 没有消息时,就先让客户端等个30s,然后服务端在这个30s内还是不停地查询消息数据,如果有新消息,就立马返回,如果还是没有新消息,就让他自己超时处理(此时客户端收到timeout响应),也有可能是正常返回空列表
- WebSocket:是 HTML5 开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。
- 优点:更好的节省服务器资源和带宽并达到实时通讯;基于TCP协议之上的高层协议,无需开发者关心通讯细节
- 现在基本上都是采用websocket协议了
webSocket
- 短轮询和长轮询之所以没法做到基于事件的完全的“边缘触发(当状态变化时,发生一个IO事件)”,这是因为服务端在有新消息产时,没有办法直接向客户端进行推送。
- 这里的根本原因在于短轮询和长轮询是基于HTTP协议实现的,由于HTTP是一个无状态协议,同一客户端的多次请求对于服务器来说并没有关系,服务端也不会去记录客户端相关的连接信息。
- 因此,所有的请求只能由客户端发起,服务端由于并不记录客户端状态,当服务端接收到新消息时,没法找到对应的客户端来推送。
- 随着HTML5的出现,全双工的websocket彻底解决了服务端推送的问题。
为什么需要websocket
websocket的出现,是为了弥补http的不足
- HTTP 协议有一个缺陷:通信只能由客户端发起。 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。
- HTML5 WebSocket 设计出来的目的就是要取代轮询和 Comet 技术,使客户端浏览器具备像 C/S 架构下桌面系统的实时通讯能力。
- 浏览器向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
- 因为 WebSocket 连接本质上就是一个 TCP 连接,所以在数据传输的稳定性和数据传输量的大小方面,和轮询以及 Comet 技术比较,具有很大的性能优势。
- 和短轮询、长轮询相比,基于websocket实现的IM服务,客户端和服务端只需要完成一次握手,就可以创建持久大的长连接,并进行随时的双向数据传输。当服务端接收到新消息时,可以通过建立的websocket连接,直接进行推送,真正做到“边缘触发”,也保证了消息到达的实时性。
websocket的特点
- 服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
- 建立在 TCP 协议之上,服务器端的实现比较容易。
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
- 数据格式比较轻量,性能开销小,通信高效。
- 可以发送文本,也可以发送二进制数据。
- 没有同源限制,客户端可以与任意服务器通信。
- 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。比如
ws://example.com:80/some/path
WebSocket 协议本质上是一个基于 TCP 协议。
- 为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息 ”Upgrade: WebSocket” 表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息 switching返回给客户端, 意思允许客户端向websocket协议转换
- 接下来, 客户端可以向服务端发起一个基于websocket协议的消息,服务端也可以主动向客户端发起websocket协议的消息,websocket协议里面通讯的单位就叫message。
- 完成这个协商之后,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
- 需要注意的问题是,除了安全和性能以外,服务端只管往 socket 里面写数据就可以了,WebSocket 的通信数据全部是以 ”\x00″ 开头以 ”\xFF” 结尾的,无论是服务端发出的数据还是客户端发送的数据都遵从这个格式,唯一不同的是客户端的 WebSocket 对象能够自动将头尾去除,获得主体数据,这就省却了在客户端处理原始数据的必要,而且 WebSocket 通信的消息总是 UTF-8 格式的。
websocket的优点是:
- 支持服务端推送的双向通信,大幅降低服务端轮询压力
- 数据交互的控制开销第,降低双方通信的网络开销
- web原生支持,实现相对简单
TCP长连接衍生的IM协议
除了websocket协议,在IM协议,还有其他一些常用的基于TCP长连接衍生的通信协议,比如XMPP协议、MQTT协议以及各种私有协议。
- 这些基于 TCP 长连接的通信协议,在用户上线连接时,在服务端维护好连接到服务器的用户设备和具体 TCP 连接的映射关系,通过这种方式客户端能够随时找到服务端,服务端也能通过这个映射关系随时找到对应在线的用户的客户端。
- 而且这个长连接一旦建立,就一直存在,除非网络被中断。这样当有消息需要实时推送给某个用户时,就能简单的通过这个长连接实现“服务端实时推送”了
但是上面提到的这些私有协议都各有优缺点,如:
- XMPP协议虽然比较成熟、扩展性也不错,但基于XML格式的协议传输上冗余比较多,在流量方面不太友好,而且整体实现上比较复杂,在如今移动网络场景下用的不多
- 轻量级的MQTT基于代理的“发布/订阅”协议,在省流量和扩展性方面比较突出,在很多消息推送场景下被广泛使用,但这个协议并不是IM领域的专有协议,因此对于很多IM下的个性化业务场景仍然需要大量复杂的扩展和开发,比如不支持群组功能、不支持离线消息
因此,对于开发人力相对充足的大厂,目前很多是基于 TCP(或者 UDP)来实现自己的私有协议,一方面私有协议能够贴合业务需要,做到真正的高效和省流;另一方面私有协议相对安全性更高一些,被破解的可能性小。目前主流的大厂很多都是采用私有协议为主的方式来实现。
其他技术
-
基于 iframe 及 htmlfile 的流(streaming)方式:这种是基于 iframe 或者 script实现的
- 主要原理:在主页面中插入一个隐藏的 iframe(script),然后这个 iframe(script)的 src属性指向服务端获取数据的接口,因为是iframe(script)是隐藏的,而且iframe(script)的 刷新也不会导致主页面刷新,所以可以为这个iframe(script)设置一个定时器,让其每隔一段时间就朝服务器发送一次请求,这样就能获得服务端的最新数据了。
- 缺点:服务器维持着长连接期会消耗资源;
-
插件提供 socket 方式:比如利用 Flash XMLSocket,Java Applet 套接口,Activex 包装的 socket。
- 优点:原生 socket 的支持,和 PC 端和移动端的实现方式相似;
- 缺点:浏览器端需要装相应的插件;
https://blog.youkuaiyun.com/Wing_93/article/details/81587809
http://www.qdker.com/archives/349.html
https://blog.youkuaiyun.com/DeepLies/article/details/77726823
https://www.cnblogs.com/duanxz/p/5194438.html