目录
1.前序
服务器推送技术:不用用户刷新发出请求,服务器主动发送实时信息到客户端。
因为HTTP协议是无状态,单向性的协议。
无状态是说客户端每一次请求都是全新的,服务器不会记录这次的你是不是上次的你。
单向性是说必须由客户端发起请求连接,服务器接受连接,把数据返回给客户端。
所以从服务器推送消息给客户端,有两种方式,一种是客户端主动定时的刷新请求,另一种就是客户端与服务器建立长连接。
2.Ajax短轮询
Ajax短轮询:定时通过Ajax查询服务器。
由客户端间隔一定时间主动发出请求,服务器响应当前数据。时间到了客户端再次发送请求,服务器返回当前数据。
这样做的好处:服务器端基本不用改造,只需要在前端加一个函数,定期发送Ajax请求就好了。
setInterval(function(){
$.ajax({
... ...
});
}, 3000);
这样做的坏处:服务器压力和资源的浪费。客户端定期就向服务器发送一条请求,由于HTTP协议的特性,即使没有数据,服务器也必须响应这一次请求,如果间隔时间设置的很短,那服务器压力就会变大。每次请求都会响应数据(不论数据是否更新)给客户端,占用带宽造成资源浪费。
还有一个很重要的缺点就是数据不同步,如果在某一次服务器刚刚响应数据后数据发生了更新,那客户端在拿到更新数据是下次一请求。所以在数据更新到下一次请求这段时间客户端的数据与服务器不同步,请求间隔时间短了服务器压力大,请求时间隔时间长了不能做到实时。
3.Ajax长轮询
由于Ajax短轮询存在数据不同步的严重缺点,因此又开发出了基于HTTP长连接的服务器推送技术——Comet。
Comet应用一种是基于Ajax的长轮询方式实现。另一种是基于长连接的服务器推模型。
Ajax的长轮询:当客户端使用Ajax发出请求时,服务器会阻塞请求直到有数据传递或超时时才返回。
客户端JS响应处理函数会在处理完服务器返回的信息后,在此发出请求,重新建立连接。
当客户端处理接收数据,重新建立连接时,服务器可能有新的数据到达;这些信息会被服务器保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。
缺点:服务器端保留响应,使用的web容器会创建一个线程用来处理请求,比如Tomcat,同时支持的连接数不超过1000,因此会导致我们这个服务性能低下。这个问题可以使用异步任务来处理,spring提供了DeferredResult。
还有一个缺点,就是实时性虽然较高,但是稍有欠缺。当服务器有了新数据响应给客户端的时候,或者客户端在处理响应的时候产生的更新数据,只能等客户端下次请求的时候再响应给客户端。
4.SSE
对于对实时性要求特别高的行业,需要完全实时性的方法来提供服务。
这个方法叫做SSE,流方式(长连接),又叫Server-sent-events(SSE),是HTML5规范的一个组成部分,和长轮询方式很像,只有一点区别,就是流方式是在客户端请求服务端并建立连接后,服务器端始终不会关闭连接。每次有数据时,就像客户端进行输出,而不像长轮询每次向客户端输出之后,都要关闭连接。
SSE主要由两部分组成:包括服务器端与浏览器端之间的通讯协议,基于纯文本的简单协议。在浏览器端可供JavaScript使用的EventSource对象
EventSource提供了三个标准事件,同时默认支持断线重连。
名称 | 说明 | 事件处理方法 |
open | 当成功与服务器建立连接时产生 | onopen |
message | 当收到服务器发来的消息时产生 | onmessage |
error | 当出现错误时产生 | onerror |
但是由于每次响应都会由tomcat返回给客户端,而tomcat默认响应完之后断开连接,然后客户端支持断线重连,又会重新连接,因此在浏览器查看网络包会发现流方式也不是发出一次请求,然后等服务器推送,而是每一次连接都会发起请求。
解决这个问题的方式就是第一次收到客户端的请求,待服务器响应的时候拿到输出流PrintWriter,然后自己向客户端去写返回的流,直到不再有 数据的时候再通过tomcat返回响应,关闭本次连接。这样流方式才是真正的一次连接,多次传输。
5.WebSocket
前边介绍的三种方式都还是在HTTP协议的基础上进行传输,其单向性的特点并没有改变。
但是WebSocket不同。
它是HTML5中的协议,实现客户端与服务器双向,基于消息的文本或二进制数据通信,是全双工。
适合于对数据的实时性要求很强,客户与服务端频繁交互的场景,如直播,实时共享桌面,多人协作等。
采用新的协议,后端需要单独实现,客户端并不是所有浏览器都支持。
与SSE进行比较:
工作方式不同,WebSocket是双向通信,SSE是单向通信。
SSE使用HTTP协议,一般只用来传送文本,WebSocket是一个独立的协议,支持传输二进制
SSE默认支持断线重连,WebSocket需要自己实现。
6.总结
1.Ajax短轮询 | 2.Ajax长轮询 | 3.SSE | 4.WebSocket | |
浏览器支持度 | 最高 | 很高 | 中(IE和Edge均不支持) | 中(早期的浏览器不支持) |
实时性 | 最低 | 较高 | 很高 | 很高 |
代码实现复杂度 | 最容易 | 较容易 | 容易 | 最复杂 |
连接性质 | 短链接 | 长连接 | 长连接 | 长连接 |
适用 | 需要服务极大量或极小量的用户,实时性要求不高 | 准实时性的应用,比较关注浏览器的兼容性 | 实时,基本都是文本交互的应用 | 实时,需要支持多样化的用户数据类型的应用或者是原生程序 |