携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第十六天,点击查看活动详情
5.3 瓶颈和“未来”发展
当前我们现在看这本书书中提到的未来都已经实现了,这些内容简单看看即可。
- SPDY (HTTP2.0)
- Ajax
- WebSocket
- Comet
- HTTP长连接
5.3.1 SPDY - The Chromium Projects
这部分内容在[[《图解HTTP》- HTTP协议历史发展(重点)]]中的HTTP2.0的历史进行了详细阐述,这里不再重复介绍。
5.3.2 Ajax
Ajax 的核心技术是名为 XMLHttpRequest 的 API,通过 JavaScript 脚本语言的调用就能和服务器进行 HTTP 通信,利用Ajax可以完成WEB页面局部更新的操作。
5.3.3 Comet
这个单词的原本含义叫做“彗星”,在WebSocket技术没有完全解决浏览器兼容问题之前,“服务器推”(Comet技术)存在广泛的应用需求,需求推动技术的发展,Comet
技术在Web端即时通讯的方案里几乎不可或缺。
在此之前的技术:
在Comet之前还有一种更早的由服务器推送实现的反向内容推送,那就是被时代逐渐抛弃的Flash
,但是使用Flash
的前提是用户自愿安装。Flash
可以很轻松的完成JS调用,并且提供XMLSocket
类接口实现了反向推送,所以很长一段时间是服务端推送的唯一办法。
还有一种技术是早就死掉的Java Applet,通过 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket完成套接字连接并且服务端推送,但是它有一个致命缺陷是Applet 无法和JavaScript 结合完成实时页面的动态刷新。
Comet如何发展的?
实时Comet本身也是依赖着Ajax的普及扩展的,所以Comet 被定义为:基于 HTTP 长连接、无须在浏览器端安装插件的“服务器推”技术为“Comet”。
Comet实现方式?
Commet的实现方式有两种,第一种是基于 AJAX 的长轮询(long-polling)方式,第二种是基于 Iframe 及 htmlfile 的流(streaming)方式。
首先简述一下第一种方式,长轮询的方式需要不断和和服务端建立HTTP握手连接,每次连接会浪费大量不必要的网络开销。
第二种是使用iframe嵌套及 html file 的流(streaming)方式的方式,iframe这个标签虽然早就被HTML不建议使用(并且废弃了),但是曾经是作为实现长链接的少数选择之一依然发挥重要作用。
原理非常简单,就是在iframe的Src标签当中嵌套获取数据的URL,在Iframe中不返回页面而是返回客户端调用的JS代码, 客户端收到服务端返回的JS调动就会去执行代码。
但是显然iframe在很多浏览器中是不允许这种嵌套JS代码调用的,所以Google后续提出使用 ActiveX ,ActiveX其实就是封装了一个基于 iframe 和 html file 的 JavaScript comet 对象。
但是因为IE旧版本和Google和FIreFox互不相容,所以这个东西在过去曾经恶心至极(在IE的兼容上),需要前端通过一些模板代码优化和处理,比较麻烦。
而使用Comet的方式是一旦发现服务端出现更新就立马返回响应。使用延迟响应的方式模拟推送功能,收到请求Comet 会先将响应置于挂起状态,当服务器端有内容更新时,再返回该响应。
相关开源组件
- Pushlet:开源的 Comet 框架,使用了观察者模型
- IComet: C++ 语言开发的支持百万并发连接的 comet/push 服务器
Comet 是过去解决服务端推送问题的过渡“插件”,虽然一定程度解决了问题,但是属于围魏救赵,本质上客户端发送请求这一点没有根本改变。
所以Comet 不需要花费过多精力,更多细节可以参考"参考资料部分的内容"。
5.3.4 HTTP 长连接特性
除了Comet 本身的诸多限制外,HTTP长连接本身也有一些值得注意的特性。
- HTTP1.1长连接存在限制,那就是客户端不应该与服务器端建立超过两个的 HTTP 连接,在IE体现为超过两个以上文件下载被阻止。
- 服务器端的性能和可扩展性,如果Ajax存在频繁请求, Comet 会长时间占用一个连接,在JAVA1.4中提供的Java.io 虽然可以实现连接空闲的时候把线程资源还给线程池,但是应对Ajax频繁请求依然会存在一些问题,使得空闲连接较少而影响性能。为此Jetty存在一些针对Comet 的优化,在相关文章 “AJAX,Comet and Jetty”中进行过详细介绍(但是很遗憾目前这篇文章已经找不到了)。
- 控制信息和数据展示分离,HTTP长连接关闭需要依赖客户端发送关闭请求,但是很多时候客户端会自行关闭网页,服务端需要把阻塞等待客户端请求转变为关闭。为了解决这个问题在AJAX的实现方式中会异步的发送一个关闭请求。基于iframe的方式则需要2个Iframe,一个负责显示,另一个负责交换控制信息,控制请求能快速响应不至于被显示信息阻塞。
- 维持心跳,所谓的维持心跳是服务端需要一种检查客户端是否活动的检查机制,定期检查客户端是否关闭连接,如果关闭连接则会进入到阻塞读的环节,如果客户端已经关闭则会进入异常状态并且关闭连接释放资源。
注意如果是基于 AJAX 的长轮询方式需要采用计时器的方式,通过计时器计时当客户端很长时间没发送请求会认为客户端已经自行关闭并且同样释放资源,保证服务器资源有效利用。
最后如果自身出现问题,也需要通知客户端然后释放资源,防止漏洞溢出。
5.3.5 WebSocket
本来属于HTML5的标准一部分,结果在出现之后逐渐脱离HTML5 成为一个独立的协议,现代主流浏览器基本全部兼容WebSocket(除了IE)。
WebSocket 通信协议在 2011 年 12 月 11 日,被 RFC 6455 - The WebSocket Protocol
定为标准。
WebSocket解决Comet和Ajax的痛点问题是一旦 Web 服务器与客户端之间建立起 WebSocket 协议的通信连接,之后所有的通信都依靠这个专用协议进行,也就是说类似协议“升级”,由于不需要客户端主动获取数据,服务端在建立连接之后可以直接向客户端推送数据。
设计目的:最初目的是解决Ajax和 Conmet 的XmlHttpRequest 附带所引发的缺陷。这两个组件的根本缺陷是只能由客户端完成请求发送。
当然并不是说只使用客户端请求无法完成内容实时更新,有一种办法是使用使用轮询的方式获取信息但是轮询意味着不断的和服务器请求连接,还有作为过渡的兼容组件"彗星"。
关于WebSocket有下面的特点:
(1)建立在 TCP 协议之上,上下兼容。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能借助HTTP进行代理。
(3)轻量化响应格式,高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
(7)减少通信量,因为一旦建立连接就会一直保持连接状态,所以HTTP首部的开销也会减少。
案例:
// Create WebSocket connection. const socket = new WebSocket('ws://localhost:8080'); // Connection opened socket.addEventListener('open', function (event) { socket.send('Hello Server!'); }); // Listen for messages socket.addEventListener('message', function (event) { console.log('Message from server ', event.data); });
基本的步骤如下:
- 握手请求。当建立HTTP连接之后,利用HTTP 的 Upgrade 首部字段,告知服务器通信协议发生改变,可以看看做HTTP连接之后再次发起一次“升级协议”请求。
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
备注:Sec-WebSocket-Key 字段内记录着握手过程中必不可少的键值。 Sec-WebSocket-Protocol 字段内记录使用的子协议。
- 因为最初的HTTP连接可能存在数据交互,所以对于之前的请求返回状态码
101 Switching Protocols
的响应。
如果不知道101是什么没啥关系,看看[[《图解HTTP》- 状态码]]这一章会发现实际上就是个没什么影响的提示信息,下面的解释自行翻译,有利于加深印象。
最后书中的WebSocket的图画的不错,基本可以直观感受到WebSocket这个单独的协议是如何和HTTP配合的。
关于WebSocket有很多细节可以展开,碍于本书面向最基本初学者缘故,所以这篇读书笔记不做过多解释,这里也上网找了一些资料作为拓展,,具体内容请阅读“参考资料”部分。
WEB历史
WEB历史讲述了HTML+CSS+JAVASCRIPT和DOM,另外介绍了现在已经不使用的Servlet,这些技术中需要提一下的是Servlet,这个看似和现在WEB没什么关系的技术,实际上依然活跃,只不过换了一种形式被Spring包装消失了,所以如果想要学好Web,掌握吃透Servlet是必不可少的。
5.4 参考资料:
5.4.1 RSS
如果你对RSS有兴趣,那么建议花点时间把下面几个链接点一遍:
- RSS - Wikipedia
- RSS - 维基百科,自由的百科全书 (wikipedia.org)
- (3 封私信) 你必读的 RSS 订阅源有哪些? - 知乎 (zhihu.com)
- 知道RSS的人越少,我就越希望它能被人知道! - 知乎 (zhihu.com)
5.4.2 XSS
Types of attacks - Web security | MDN (mozilla.org)
5.4.3 Websocket
最后是有关Websocket的API参考部分:
WebSocket - Web API 接口参考 | MDN (mozilla.org)
以及一位阿里大佬介绍的WebSocket的内容,另外最后相关连接的参考资料比较有阅读价值,建议收藏之:
WebSocket协议:5分钟从入门到精通 - 程序猿小卡 - 博客园 (cnblogs.com)
5.4.4 SPDY
SPDY的参考网站: http://www.chromium.org/spdy/
这部分内容我们可以结合HTTP2.0 进行扩展,因为是已经实现的东西,并且查看相关的新特性支持。
5.4.5 Comet
Comet技术详解:基于HTTP长连接的Web端实时通信技术 - 知乎 (zhihu.com)
关于更多Comet的百科和历史发展可以看下面的百科,本小节的内容也包含在百科内详细介绍: