换个角度解决问题:服务端推送技术

Pull 模型的问题

“Pull”指的是去主动发起行为获取消息,一般在客户端 / 服务器(C/S,Client/Server)或浏览器 / 服务器(B/S,Browser/Server)交互中,客户端或浏览器主动发起的网络请求数据的行为。

“Poll”,尽管在某些场景下也和 Pull 通用了,但在计算机网络的领域里,通常把它解释为“轮询”,或者“周期性查询”,在 Pull 的基础上增加了“周期性”的概念,这也是它和 Pull 相比最本质的区别。

Push 相比 Pull 而言,具备这样两个明显的优势:

  • 高效性。如果没有更新发生,就不会有任何更新消息推送的动作,即每次消息推送都发生在确确实实的更新事件之后,都是有意义的,不会出现请求和响应的资源浪费。
  • 实时性。事件发生后的第一时间即可触发通知操作,理论上不存在任何可能导致通知延迟的硬伤。

有趣的是,事实上 Pull 的应用却远比 Push 更广泛,特别是在分布式系统中。这里有多个原因,其中很重要的一条是:

服务端不需要维护客户端的列表,不需要知晓客户端的情况,不需要了解客户端查询的策略。这有助于把服务端从对客户端繁重的管理工作中解放出来,而成为无状态的简单服务,变得具备幂等性(idempotent,指执行多次和执行一次的结果一样),更容易横向扩展。

服务端推送技术

Comet

客户端发送一个普通的 HTTP 请求到服务端以后,服务端不像以往一样在处理后立即返回数据,而是保持住连接不释放,每当有更新事件发生,就使用分块传输的方式返回数据

若干次数据返回以后可以完成此次请求响应过程(分块传输返回长度为 0 的块,表示传输结束),等待客户端下一次请求发送。这种过程看起来也属于轮询,但是每个周期可包含多次服务端数据返回,因而也被形象地称为“长轮询”(Long Polling)。

在服务端推送技术中,Comet 最大的好处是,它 100% 由 HTTP 协议实现,当然,分块传输要求 HTTP 至少是 1.1 版本。但也正因为这点,它也存在一些弊端,比如,客户端必须在服务端结束当次传输后才能向服务端发送消息;HTTP 协议限制了它在每次请求和响应中必须携带完整的头部,这在一定程度上也造成了浪费(这种为了传输实际数据而使用的额外开销叫做 overhead)。

image.png

在 Comet 方式下,看起来服务端有了推送行为,其实只是对于客户端请求有条件、讲时机的多次返回,因此我们把它称为服务端“假 Push”。

WebSocket

HTML 5 规范定义了 WebSocket 协议,它可以通过 HTTP 的端口(或者 HTTPS 的端口)来完成,从而最大程度上对 HTTP 协议通透的防火墙保持友好。但是,它是真正的双向、全双工协议,也就是说,客户端和服务端都可以主动发起请求,回复响应,而且两边的传输都互相独立。

它在网络分层模型中位于 TLS 上方,因此他可以使用和 HTTP 一样的加密方式传输:

HTTP → WS
HTTPS → WSS

例子:

  • 请求
GET wss://echo.websocket.org/?encoding=text HTTP/1.1
Host: echo.websocket.org
Origin: https://www.websocket.org
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: xxx
... (省略其它 HTTP 头)

这是一个普普通通的 HTTP GET 请求,但是 URL 是以加密连接“wss”开头的,并且有几个特殊的 HTTP 头:Origin 指出了请求是从哪个页面发起的,Connection: Upgrade 和 Upgrade: websocket 这两个表示客户端要求升级 HTTP 协议为 WebSocket。

  • 响应

HTTP/1.1 101 Web Socket Protocol Handshake Connection: Upgrade Sec-WebSocket-Accept: xxx Upgrade: websocket ... (省略其它 HTTP 头)

更多推送技术

一下技术与 Comet/WebSocket 类似:

  1. SSE,即 Server-Sent Events,又叫 EventSource,是一种已被写入 HTML 5 标准的服务端事件推送技术,它允许客户端和服务端之间建立一个单向通道,以让服务端向客户端单方向持续推送事件消息;
  2. 为了提高性能,HTTP/2 规范中新添加的服务端推送机制,我们在 [第 01 讲] 中提到过,并在该讲的扩展阅读中有它的原理介绍;
  3. WebRTC,即 Web Real-Time Communication,它是一个支持网页进行视频、语音通信的协议标准,不久前已被加入 W3C 标准,最新的 Chrome 和 Firefox 等主流浏览器都支持;
  4. 还有一些利用浏览器插件和扩展达成的服务端推送技术,比如使用 Flash 的 XMLSocket,比如使用 Java 的 Applet,但这些随着 HTML 5 的普及,正慢慢被淘汰。

扩展阅读

  1. 文中提到了跨域问题,如果感兴趣,推荐你阅读 MDN 的 HTTP 访问控制(CORS) 这篇文章。
  2. TutorialsPoint 的 WebSocket 系统教程,对于本文介绍的 WebSocket 协议,需要进一步了解的一个好去处。
  3. 关于 HTTP Update 头的 RFC 2616 协议片段 和 WebSocket 的 RFC 6445,你也许对响应和请求中的其它 HTTP 头心存疑问,和之前介绍的 HTTP 的 RFC 协议一样,你通常不需要仔细阅读,但它是对协议有问题时的最终去处。
  4. Stream Updates with Server-Sent Events,一篇非常好的介绍 SSE 基础,和同类技术比较优劣,并给出代码示例的文章;如果你对 WebRTC 感兴趣,那么可以先看看这个胶片,再阅读这篇基础知识 Getting Started with WebRTC。
公众号:码农架构

你可能感兴趣的:(换个角度解决问题:服务端推送技术)