跳到主要内容

SockJS - 网络消息传递并非易事

·5 分钟阅读
Marek Majkowski

“实时网络”或使用网络浏览器的消息传递的想法已经存在很长时间了。 最初它被称为“长轮询”,然后是“Comet”,最新的化身被称为“WebSockets”。 毫无疑问,它正朝着正确的方向发展,WebSockets 是一项简洁的技术。

但在争取实时能力的过程中,我们忽略了真正重要的事情:如何实际使用消息传递。 在 Web 环境中,一切都是请求-响应驱动的,将典型的 Web 堆栈与异步消息传递结合起来并非易事。

现状

已经有很多尝试创建通用组件,它可以加入 Web 堆栈,并像数据库处理数据一样处理“消息传递”。

但问题是,消息传递的异步性质和浏览器跨域限制意味着,为了使“Comet”工作,您需要使用特定的 Web 堆栈。 这是典型的供应商锁定案例。

新方法

至少过去是这样。 您可以使用 Web 消息传递框架,但您几乎被它束缚住了。

直到不久前,Socket.io 项目才出现。 它构建在 Node.js 之上,这赋予了它独特的地位——不仅 Node.js 中的一切都已经完全异步(几乎不可能搞砸),而且它还使用了一种 Web 环境中已经使用的通用语言。

早期的 Socket.io 开发专注于消息传递,换句话说,如何将消息发送到 Web 浏览器和从 Web 浏览器接收消息。 与 Web 开发人员的合同很简单:这是一个异步传输层,您可以在此之上构建您的应用程序逻辑 JavaScript。

开发人员需要编写一个薄 JavaScript 层,将 Socket.io 连接与应用程序连接起来,实现细节留给开发人员。 应用程序可以是 Node 或使用任何其他堆栈。 它可以使用几乎任何方法连接,例如 Redis、RabbitMQ 或 HTTP 回调。

但最近 Socket.io 改变了重点,它不再是一个简单的传输,它开始成为一个完整的消息传递堆栈,具有以下特点:

  • 消息确认
  • 广播 / “房间”
  • 多路复用
  • 易失性消息

没有银弹

但这里有一个问题:如果您构建消息传递语义,则消息传递库开始成为一个框架,并很快与平台绑定。

考虑一下,即使您尝试构建一个简单的“广播”抽象,您也必然需要回答许多不明显的问题:

  • 应用程序将如何部署?(仅限于一台服务器还是使用底层消息总线进行扩展? 使用什么消息总线? 它如何与 HTTP 负载均衡器配合使用?)
  • 谁有权“订阅”该广播数据? 它是公开的吗? 如何设置权限?
  • 谁可以发布消息? 订阅者如何可靠地识别消息的作者?

请记住,“广播”是一个非常简单的抽象,实际上每个人都以不同的方式使用消息传递,并且很难创建一个通用的消息传递框架。 消息传递框架做出的大多数决定实际上都是特定于应用程序的

  • 授权(谁可以听到什么以及在哪里发布)
  • 数据理解(如何进行值 + 更新? 什么是差异算法?)
  • 在线状态(所有应用程序都需要略有不同的含义)

我很高兴 Socket.io 的开发进展顺利,并为此祈祷。 但在我看来,它关注了错误的问题:我不需要另一个与特定平台绑定的固执己见的消息传递框架。

相反,我只需要一个稳定的传输层。

后续步骤

Socket.io 指明了方向——存在一个简单而稳定的库的空间,它可以解决消息传递问题,从而实现类似 WebSockets 的 API,直到原生实现得到广泛部署。 所有这一切都不需要定义消息传递模型,拜托了。

这是我的回复:SockJS - 一个具有类似 WebSockets API 的库,仅关注传输层。 虽然项目还很年轻,但在我看来,它已经比其他类似的库要好。

该项目分为两个部分

如果您想看到它运行,这里有一些托管 QUnit 测试的实时部署

SockJS 背后的主要假设是

  • API 应该尽可能地模仿 WebSocket API。
  • 服务器端部分应该很简单,所有的复杂性都应该由浏览器库处理。 (假设只有一个浏览器库,并且会有许多服务器端实现。 我们有一个 SockJS Node 服务器,我们希望至少做一个 Erlang 服务器。)
  • 内部没有 Flash,只有 JavaScript。
  • 回退到缓慢而笨拙的轮询传输,当客户端位于企业防火墙和代理后面时很有用。
  • 所有传输都必须是跨域的——开发人员必须能够将 SockJS 服务器作为其基础设施的独立部分托管。
  • 支持常见的负载均衡策略:使用基于 JSESSIONID cookie 的粘性会话或基于前缀的均衡。

未来

解决消息传递问题只是第一步。 最终目标是为 Web 应用程序创建一个通用的消息传递框架,但这绝非易事。 这将需要大量的工作和许多失败的尝试。 这就是为什么拥有一个稳定、设计良好、可重用的传输层非常重要的原因。

(文章也可在 github 页面上找到)

© . All rights reserved.