本文翻译自【The modern Web】,喜欢看原文的朋友,可以移步。
===== 我是刚过了母亲节的分隔线 =====
让我们回顾一下从 Web 技术的创始之初到今天都经历了哪些技术,并对将会出现并使用的技术进行预览。
Cowboy 兼容于本章节中提及的所有技术,当然尚不包含 HTTP/2.0 ,因为在书写本文时世界上尚未有相应的实现。
史前 Web
HTTP 最初被创建用于支持 HTML 页面的获取,且最初仅包含 GET 方法用于获取内容。该初始版本有文档记录,并在业界称为 HTTP/0.9 。到了 HTTP/1.0 ,协议中定义了 GET 、 HEAD 和 POST 方法,已经能够通过 POST 请求发送数据了。
HTTP/1.0 以一种非常简单的方式工作。首先建立到服务器的 TCP 连接,然后发送相应的请求,最后服务器发回应答同时关闭该 TCP 连接。
简单的讲,HTTP/1.0 并不高效。打开一个 TCP 连接需要花费一定的时间,因为这个缘故,一些包含许多资源的页面在加载的时候,会比原本的速度更慢。
最近几年大多数改进都集中在减少这个加载的时间,并减少发送请求时的延迟。
HTTP/1.1
HTTP/1.1 在 HTTP/1.0 之后很快就问世了,其通过增加 keep-alive 机制允许在相同连接上发送多个请求,通过增加 chunk 机制允许客户端或服务器以流式方式发送消息体。
HTTP/1.1 协议定义了 OPTIONS 、 GET 、 HEAD 、 POST 、 PUT 、 DELETE 、 TRACE 和 CONNECT 方法。另外在最近几年又增加了 PATCH 方法。同时由于在 HTTP/1.1 协议中引入了一些新的 header 增加了其针对缓存的处理能力。
但 HTTP/1.1 仍旧按照 HTTP/1.0 那种模式被使用着,除了相应的连接会被保持用于后续的请求。这就是客户端侧可以进行一种称为 pipelining 操作的真实缘由:连续发送许多请求,之后会以相同的顺序处理接收到的应答。
REST
HTTP/1.1 的设计受到了 REST (REpresentational State Transfer) 结构风格的影响,这是一种基于松耦合方式连接分布式系统的架构风格。
REST 定义了系统必须遵守的限制以约束系统具有 RESTful 性质。若系统没有完全遵从这些限制,则不能认为其具有 RESTful 性质。
REST 是明确划分了客户端和服务器所关注内容的分离的客户端-服务器架构。他们之间通过引用资源进行通信。资源可以被定义,也可以被操纵。资源的表示包括 media 类型和其是否可被缓存和怎样缓存的相关信息。超媒体(Hypermedia)确定了资源之间是如何关联的,以及应该怎样被使用。REST 同样是无状态的。所有的请求本身都包含了完整的信息用于执行相应的动作。
HTTP/1.1 协议内容定义了用于实现 RESTful 系统的所有方法、header 和语义。
REST 最常用于设计 web 应用 API 上,即通常上被可执行代码直接使用。
XmlHttpRequest
XmlHttpRequest 是通过 AJAX 技术为世人所熟知的,通过该技术,运行在 web 页面上的 Javascript 代码就能够向服务器发起异步请求了。这就是静态网站向动态 web 应用所迈出的万里长征第一步。
XmlHttpRequest 在底层仍旧采取先发送 HTTP 请求,再等待应答的模式,但是过程中 Javascript 代码将能够继续运行,直到应答的到来。届时 Javascript 就能够从之前定义好的回调函数中接收到相应的应答。
当然,这模式限定了只能由客户端发起请求,服务器仍旧无法靠自己主动推送数据到客户端,所以新技术又由此而诞生。
Long-polling
长轮询
轮询是一种用于解决服务器无法直接推送数据给客户端这一问题所使用的技术。所以客户端不得不反复创建连接,发送请求,获取应答,几秒之后再次重新执行上述操作。这从总体上来说是非常耗费资源的,并且增加客户端接收收据前的额外延迟。
当用户需要即时事件通知,而不是要等其主动刷新页面后才能发现有事件的情形下,轮询技术有必要实现额外的消息队列或其它类似的机制。一个典型的例子就是聊天室应用。
长轮询可以通过减少连接数量,进而减少服务器负载,并且可以改进应答延迟的问题,因为只要服务器有应答可发送,客户端就可以获取。
长轮询的工作方式和轮询类似,除了发送请求后不会立即获得应答这一点。取而代之的是,服务器会保持当前连接处于打开状态,直到服务器侧确实有应答需要发送时。在客户端获取到应答后,会再次发起一个新的请求,并重新进入等待应答状态。
到目前为止,你可能已经猜出来了,长轮询技术其实只不过是个 hack ,正如所有 hack 都会面临不可预期的问题一样,对于长轮询而言,其经常无法很好的用于存在 proxy 的情况下。
HTML5
HTML5 是 HTML4 之后的版本。但是 HTML5 的出现是为了解决特定的问题:动态 web 应用。
HTML 最初被设计成用于编写网站的 web 页面。但是很快人们和一些公司就希望使用 HTML 编写越来越复杂的网站,也就是最终被称为 web 应用的东东。举例来说,web 应用就是你的新闻阅读器,位于浏览器上 email 客户端,或者你的视频流媒体网站。
因为 HTML 本身是无法满足需要的,所以 web 应用开始使用具有专利性质的解决方案,通常是基于插件实现的。这种情况当然是不完美的,但是对大多数人来说上已经足够。
然而,对于标准解决方案的渴求已经变得越来越迫切。浏览器需要能够本地播放媒体;浏览器需要能在其上画任何东西;浏览器需要一种高效的方式将事件流发送到服务器,同时还要能够从服务器获取事件流。
上述需求最终促成了 HTML5 的诞生。在本文写成之时,HTML5 已经被标准化了。
EventSource
EventSource 有时被称为“服务器发送事件机制”。其允许服务器推送数据到 HTML5 应用。
EventSource 采用从服务器到客户端的单向通信通道。客户端侧无法和服务器进行沟通,除非使用 HTTP 请求。
EventSource 由如下两部分构成:
- 一个 Javascript 对象,用于建立到服务器的 EventSource 连接的 ;
- 一份轻量的、基于 HTTP/1.1 连接的、能够发送事件给客户端的协议。
EventSource 是一种轻量级的解决方案,仅适用于处理 UTF-8 编码的文本。二进制数据和以其他方式编码的文本数据不能用于此协议。一种更“重”、但是更通用的实现方案可以通过 Websocket 实现。
Websocket
websocket 是构建于 HTTP/1.1 之上的协议。其在客户端和服务器之间提供了双向通信的通道。通信是异步模式的,并且在两侧可以同时进行。
websocket 模型由如下两部分构成:
- 一个 Javascript 对象,用于建立到服务器的 Websocket 连接;
- 一份用于发送数据到服务器或客户端的、二进制协议。
在 Websocket 连接上可以传输 UTF-8 编码的文本数据,或者二进制数据。该协议同时实现了 ping/pong 机制的支持,允许服务器和客户端确认当前连接仍旧处于活跃状态。
Websocket 连接能被用于传输任何类型的数据,无论小块还是大块,文本或者二进制。鉴于上述特点,Websocket 有时会被用于跨系统通信。
SPDY
SPDY 的目标是减少页面加载时间,该目标的实现采用了如下方式:为每个服务器打开一个连接,并为后续请求保持该连接的打开,以及通过压缩 HTTP header 来减少请求大小。
SPDY 兼容于 HTTP/1.1 语义,而事实上,可以将其看作只是处理 HTTP 请求和应答另一种方式,因为其采用了二进制数据帧替代了基于文本的协议。SPDY 同样允许服务器在收到请求后发送额外应答。这意味着服务器允许在客户端(再次)请求资源前,发送和(前一次)请求相关的资源(应答),可以减少网站加载的延迟(其实也就是类似长轮询的功能)。
SPDY 尚处于试验阶段,但已经被证明非常成功了,其会被作为 HTTP/2.0 标准基础协议。
使用了 TLS Next Protocol Negotiation 的浏览器将可以无缝升级到 SPDY 连接上,如果该浏览器支持 SPDY 的话。
该协议本身尚有一些缺点,将会在 HTTP/2.0 中被修复。
HTTP/2.0
HTTP/2.0 是对 HTTP/1.1 协议的(望穿秋水的)更新。其基于 SPDY 协议,虽然在本文写成的时候其已经做了相当多的改进。
HTTP/2.0 是异步双向通信协议。
HTTP/2.0 计划在 2014 下半年可用。