1) 为什么 WebSockets 协议更好?
WebSockets 更适合涉及低延迟通信的情况,尤其是对于客户端到服务器消息的低延迟。对于服务器到客户端的数据,您可以使用长期连接和分块传输获得相当低的延迟。但是,这对客户端到服务器的延迟没有帮助,因为需要为每个客户端到服务器的消息建立新的连接。
对于现实世界的 HTTP 浏览器连接,您的 48 字节 HTTP 握手是不现实的,因为请求中通常会发送数千字节的数据(双向),包括许多标头和 cookie 数据。以下是使用 Chrome 的请求/响应示例:
示例请求(2800 字节包括 cookie 数据,490 字节不包括 cookie 数据):
GET / HTTP/1.1
Host: www.cnn.com
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.68 Safari/537.17
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: [[[2428 byte of cookie data]]]
示例响应(355 字节):
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 13 Feb 2013 18:56:27 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: CG=US:TX:Arlington; path=/
Last-Modified: Wed, 13 Feb 2013 18:55:22 GMT
Vary: Accept-Encoding
Cache-Control: max-age=60, private
Expires: Wed, 13 Feb 2013 18:56:54 GMT
Content-Encoding: gzip
HTTP 和 WebSocket 都具有相同大小的初始连接握手,但是对于 WebSocket 连接,初始握手只执行一次,然后小消息只有 6 个字节的开销(2 个用于标头,4 个用于掩码值)。延迟开销不是来自标头的大小,而是来自解析/处理/存储这些标头的逻辑。此外,TCP 连接建立延迟可能是比每个请求的大小或处理时间更大的因素。
2) 为什么要实现它而不是更新 HTTP 协议?
正在努力重新设计 HTTP 协议以实现更好的性能和更低的延迟,例如 SPDY、HTTP 2.0 和 QUIC。这将改善普通 HTTP 请求的情况,但 WebSockets 和/或 WebRTC DataChannel 的客户端到服务器数据传输的延迟很可能仍然低于 HTTP 协议(或者它将用于看起来很像 WebSockets 的模式反正)。
更新:
这是一个思考网络协议的框架:
-
TCP:低层、双向、全双工、保证顺序的传输层。不支持浏览器(通过插件/Flash 除外)。
-
HTTP 1.0:基于 TCP 的请求-响应传输协议。客户端发出一个完整的请求,服务器给出一个完整的响应,然后关闭连接。请求方法(GET、POST、HEAD)对服务器上的资源具有特定的事务意义。
-
HTTP 1.1:保持 HTTP 1.0 的请求-响应性质,但允许连接对多个完整请求/完整响应(每个请求一个响应)保持打开状态。请求和响应中仍有完整的标头,但连接被重用且未关闭。 HTTP 1.1 还添加了一些额外的请求方法(OPTIONS、PUT、DELETE、TRACE、CONNECT),它们也具有特定的事务含义。然而,正如 HTTP 2.0 草案提案的 introduction 中所述,HTTP 1.1 管道并未广泛部署,因此这极大地限制了 HTTP 1.1 在解决浏览器和服务器之间延迟方面的实用性。
-
长轮询:对 HTTP(1.0 或 1.1)的一种“破解”,其中服务器不会立即响应(或仅使用标头部分响应)客户端请求。在服务器响应之后,客户端立即发送一个新请求(如果通过 HTTP 1.1,则使用相同的连接)。
-
HTTP 流式传输:允许服务器向单个客户端请求发送多个响应的多种技术(多部分/分块响应)。 W3C 使用text/event-stream MIME 类型将其标准化为Server-Sent Events。浏览器 API(与 WebSocket API 非常相似)称为 EventSource API。
-
Comet/服务器推送:这是一个涵盖长轮询和 HTTP 流的总称。 Comet 库通常支持多种技术,以尝试最大化跨浏览器和跨服务器支持。
-
WebSockets:基于 TCP 的传输层,使用 HTTP 友好的升级握手。与作为流传输的 TCP 不同,WebSockets 是基于消息的传输:消息在线路上进行分隔,并在交付给应用程序之前完整地重新组装。 WebSocket 连接是双向的、全双工的和长寿命的。在初始握手请求/响应之后,没有事务语义,并且每条消息的开销很小。客户端和服务器可以随时发送消息,并且必须异步处理消息接收。
-
SPDY:Google 发起的一项提议,使用更高效的有线协议扩展 HTTP,但保留所有 HTTP 语义(请求/响应、cookie、编码)。 SPDY 引入了一种新的帧格式(以长度为前缀的帧),并指定了一种将 HTTP 请求/响应对分层到新的帧层上的方法。可以压缩标头,并且可以在建立连接后发送新的标头。在浏览器和服务器中有 SPDY 的实际实现。
-
HTTP 2.0:与 SPDY 具有相似的目标:减少 HTTP 延迟和开销,同时保留 HTTP 语义。当前草案源自 SPDY,定义了升级握手和数据帧,与用于握手和帧的 WebSocket 标准非常相似。另一个 HTTP 2.0 草案提案 (httpbis-speed-mobility) 实际上将 WebSockets 用于传输层,并将 SPDY 多路复用和 HTTP 映射添加为 WebSocket 扩展(WebSocket 扩展在握手期间协商)。
-
WebRTC/CU-WebRTC:建议允许浏览器之间的点对点连接。这可以实现更低的平均和最大延迟通信,因为底层传输是 SDP/数据报而不是 TCP。这允许无序传送数据包/消息,从而避免 TCP 延迟峰值问题,该问题是由丢弃的数据包导致延迟所有后续数据包的传送(以保证按顺序传送)。
-
QUIC:是一种实验性协议,旨在减少与 TCP 相比的 Web 延迟。从表面上看,QUIC 与在 UDP 上实现的 TCP+TLS+SPDY 非常相似。 QUIC 提供相当于 HTTP/2 的多路复用和流量控制,相当于 TLS 的安全性,以及相当于 TCP 的连接语义、可靠性和拥塞控制。由于 TCP 是在操作系统内核和中间盒固件中实现的,因此对 TCP 进行重大更改几乎是不可能的。然而,由于 QUIC 是建立在 UDP 之上的,它没有这样的限制。 QUIC 针对 HTTP/2 语义进行了设计和优化。
参考文献:
HTTP:
服务器发送事件:
WebSockets:
SPDY:
HTTP 2.0:
WebRTC:
QUIC: