一、服务器推送技术
1、服务器推送技术的兴起
一下部分内容摘自百科
随着AJAX技术的兴起,让广大开发人员又一次看到了使用浏览器来替代桌面应用的机会,并且这次机会非常大。AJAX将整个页面的刷新变成页面局部的刷新,并且数据的传送是以异步方式进行,这使得网络延迟带来的视觉差异将会消失。AJAX还利用DHTML和丰富的JavasSript语言来模拟桌面系统的各种事件和响应过程,以及平滑滚动和拖拽的效果。还不止这些,更有一些IT巨头(Google、Sun、Oracle等)提供了非常丰富的AJAX开发工具,使得开发和调试AJAX应用变得简单高效,并且开发的AJAX应用还可以跨越各种浏览器和操作系统。在这种情况下基于AJAX的Web应用迅速涌起,吞噬着原有桌面系统的份额。聊天工具、邮件阅读器、博客编辑器,甚至是Office办公软件和文字处理软件在浏览器中都有着美丽的外观和几乎可以与桌面系统媲美的交互界面。Google更是提出“有了浏览器和Google,就不需要微软”的口号和策略。在Ajax的世界中,除了传统的CAD设计软件和大型游戏软件等因为对系统硬件的苛刻需求,还离不开桌面系统以外,似乎其他所有的应用都可以变成Web应用了。
但是,在浏览器中的AJAX应用中存在一个致命的缺陷无法满足传统桌面系统的需求。那就是“服务器发起的消息传递(Server-Initiated Message Delivery)”。在很多的应用当中,服务器软件需要向客户端主动发送消息或信息。因为服务器掌握着系统的主要资源,能够最先获得系统的状态变化和事件的发生。当这些变化发生的时候,服务器需要主动地向客户端实时地发送消息。例如股票的变化。在传统的桌面系统中,这种需求没有任何问题,因为客户端和服务器之间通常存在着持久的连接,这个连接可以双向传递各种数据。而基于HTTP协议的Web应用却不行。上节中也提到过,在Web世界中,服务器永远是被动地发送数据,前提是客户端必须先发送请求。浏览器其实并不知道服务器的信息什么时候会有改变,为了模拟实时的交流,或者不想错过某些信息,只能通过轮询(Polling)技术不断刷新页面来获得最新的数据。这种方式不但浪费服务器的资源,最重要的是每次建立(或关闭)新的HTTP连接都有一定的延迟,这种延迟使得频繁信息传递的应用无法忍受。于是就产生了“服务器推送技术”。
2、应用场景
服务器推送技术干嘛用?就是让用户在使用网络应用的时候,不需要一遍又一遍的去手动刷新就可以及时获得更新的信息。大家平时在上各种视频网站时,对视频节目进行欢乐的吐槽和评论,会看到各种弹幕,当然,他们是用flash技术实现的,对于我们没有用flash的应用,一样可以实现弹幕。又比如在股票网站,往往可以看到,各种股票信息的实时刷新,上面的这些都是基于服务器推送技术。
一般实现服务推送技术有以下几种方式,Ajax短轮询,**Comet,WebSocket。**以下就重点介绍每个方式的实现。
二、Ajax短轮询
1、定义
就是用一个定时器不停的去网站上请求数据。比如定义一个定时器,每3s请求一次。虽然实现简单,但问题也很明显,存在延迟时间。并且不断去请求服务器端给服务器端造成一定的压力
setInterval(function() { $.ajax({ …………………… }); }, 3000);
2、特点
- 服务端基本不用改造
- 服务器沉重压力和资源的浪费
- 数据同步不及时
三、Comet
“服务器推”是一种很早就存在的技术,以前在实现上主要是通过客户端的套接口,或是服务器端的远程调用。因为浏览器技术的发展比较缓慢,没有为“服务器推”的实现提供很好的支持,在纯浏览器的应用中很难有一个完善的方案去实现“服务器推”并用于商业程序。,因为 AJAX 技术的普及,gmail等等在实现中使用了这些新技术;同时“服务器推”在现实应用中确实存在很多需求。称这种基于 HTTP长链接、无须在浏览器端安装插件的“服务器推”技术为“Comet”。他主要由两种实现。ajax的长轮询和SSE
3.1 AJAX 的长轮询
1、定义
由客户端发起请求,但是服务端并不会立即返回,而是保持该链接。知道有新的数据更新的时候才返回响应,并关闭链接。客户端则处理完相应信息之后,再重新发送给服务器新的请求。
实现方式
①Servlet3里的异步任务
②Spring的DeferedResult
2、特点
- 实时性好,性能较高
- 长期占用链接,丧失了无状态高并发特点,并且服务器处理链接有限。当达到瓶颈时无法响应新的请求
适用于股票和实时通讯系统
3.2 SSE
1、定义
严格地说,HTTP 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming)。
也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。
SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。
2、特点
- SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
- SSE 属于轻量级,使用简单;WebSocket 协议相对复杂。
- SSE 默认支持断线重连,WebSocket 需要自己实现。
- SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。
- SSE 支持自定义发送的消息类型。
3、SSE的使用规范
HTTP 头信息
服务器向浏览器发送的 SSE 数据,必须是 UTF-8 编码的文本,具有如下的 HTTP头信息。
- Content-Type: text/event-stream
- Cache-Control: no-cache
- Connection: keep-alive
上面三行之中,第一行的Content-Type必须指定 MIME 类型为event-steam。
消息格式
每一次发送的信息,由若干个message组成,每个message之间用\n\n分隔。每个message内部由若干行组成,每一行都是如下格式。
[field]: value\n
上面的field可以取四个值。
四、WebSocket通信
1、什么是webSocket
WebSocket ——一种在2011 年被互联网工程任务组(IETF)标准化的协议。
WebSocket解决了一个长期存在的问题:既然底层的协议(HTTP)是一个请求/响应模式的交互序列,那么如何实时地发布信息呢?AJAX提供了一定程度上的改善,但是数据流仍然是由客户端所发送的请求驱动的。还有其他的一些或多或少的取巧方式(Comet).
WebSocket规范以及它的实现代表了对一种更加有效的解决方案的尝试。简单地说,WebSocket提供了“在一个单个的TCP连接上提供双向的通信,结合WebSocket API,它为网页和远程服务器之间的双向通信提供了一种替代HTTP轮询的方案"。但是最终它们仍然属于扩展性受限的变通之法。也就是说,WebSocket 在客户端和服务器之间提供了真正的双向数据交换。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。
Web浏览器和服务器都必须实现 WebSockets 协议来建立和维护连接。
2、特点
- HTML5中的协议,实现与客户端与服务器双向,基于消息的文本或二进制数据通信
- 适合于对数据的实时性要求比较强的场景,如通信、直播、共享桌面,特别适合于客户与服务频繁交互的情况下,如实时共享、多人协作等平台。
- 采用新的协议,后端需要单独实现
- 客户端并不是所有浏览器都支持
3、WebSocket通信握手
Websocket借用了HTTP的协议来完成一部分握手
客户端的请求
Connection 必须设置 Upgrade,表示客户端希望连接升级。
Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。
Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算 SHA-1 摘要,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为 Websocket 协议。
Sec-WebSocket-Version 表示支持的 Websocket 版本。RFC6455 要求使用的版本是 13,之前草案的版本均应当弃用。
服务器端
Upgrade: websocket
Connection: Upgrade
依然是固定的,告诉客户端即将升级的是 Websocket 协议,而不是mozillasocket,lurnarsocket或者shitsocket。
然后, Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key 。
后面的, Sec-WebSocket-Protocol 则是表示最终使用的协议。
至此,HTTP已经完成它所有工作了,接下来就是完全按照Websocket协议进行
4、WebSocket通信-STOMP协议
WebSocket是个规范,在实际的实现中有HTML5规范中的WebSocket API、WebSocket的子协议STOMP。
STOMP(Simple Text Oriented Messaging Protocol)
- 简单(流)文本定向消息协议
- STOMP协议的前身是TTMP协议(一个简单的基于文本的协议),专为消息中间件设计。是属于消息队列的一种协议, 和AMQP, JMS平级. 它的简单性恰巧可以用于定义websocket的消息体格式. STOMP协议很多MQ都已支持, 比如RabbitMq, ActiveMq。
- 生产者(发送消息)、消息代理、消费者(订阅然后收到消息)
- STOMP是基于帧的协议
5、WebSocket 与SSE的对比
WebSocket 与 SSE 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。
SSE和WebSocket相比的优势。最大的优势就是便利:不需要添加任何新组件,用任何你习惯的后端语言和框架就能继续使用。你不用为新建虚拟机、弄一个新的IP或新的端口号而劳神,就像在现有网站中新增一个页面那样简单。可以称为既存基础设施优势。
总体来说,WebSocket 更强大和灵活。因为它是全双工通道,可以双向通信;SSE 是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。如果浏览器向服务器发送信息,就变成了另一次 HTTP 请求。
五、技术比较
1、短轮询 |
2、长轮询 |
3、SSE |
4、WebSocket |
|
浏览器支持度 |
最高 |
很高 |
中(IE和Edge均不支持) |
中(早期的浏览器不支持) |
实时性 |
最低 |
较高 |
很高 |
很高 |
代码实现复杂度 |
最容易 |
较容易 |
容易 |
最复杂 |
连接性质 |
短连接 |
长连接 |
长连接 |
长连接 |
适用 |
需要服务极大量或极小量的用户,实时性要求不高 |
准实时性的应用,比较关注浏览器的兼容性 |
实时,基本都是文本交互的应用 |
实时,需要支持多样化的用户数据类型的应用或者是原生程序 |
当然技术没有好坏之分,具体还要看使用场景。就比如京东用的什么?Ajax短轮询。京东的痛点是什么?要用有限的资源来为千万级甚至上亿的用户提供服务,如果是用长连接,对于接入的服务器,比如说Nginx,是很大的压力,光是为用户维持这个长连接都需要成百上千的Nginx的服务器,这是很划不来的。因为对于京东这类购物网站来说,用户的浏览查询量是远远大于用户下单量的,京东需要注重的是服务更多的用户,而且相对于用户浏览页面的图片等等的流量而言,这点带宽浪费占比是很小的。所以我们看京东的付款后的实现,是用的短轮询机制,而且时长放大到了5秒。希望大家了解相关的技术,并渗透到具体业务场景中,选择最合适的方案。