基于 Web 的实时通信与 REST 范式不兼容吗?
Posted
技术标签:
【中文标题】基于 Web 的实时通信与 REST 范式不兼容吗?【英文标题】:Is web-based real-time communication incompatible with REST paradigm? 【发布时间】:2012-12-17 18:27:40 【问题描述】:在过去几年中,Web 应用程序经历了巨大的范式转变。
十年前(不幸的是,即使是现在),Web 应用程序只存在于 重量级 服务器中,处理从数据到演示格式的所有内容,并发送到只呈现服务器输出的愚蠢客户端(浏览器)。
然后 AJAX 加入了游戏,网络应用程序开始变成介于服务器和浏览器之间的东西。
在 AJAX 的高潮期间,Web 应用程序逻辑开始完全依赖于浏览器。我认为这是 HTTP RESTful API 开始出现的时候。突然间,每一项新服务都有其种类 RESTful API,突然间javascript MV* 框架开始像爆米花一样流行起来。移动设备的使用也大大增加,REST 非常适合这类场景。我在这里说“一种 RESTful”,因为几乎所有声称是 REST 的 API 都不是。但这是一个完全不同的故事。
事实上,我成了一个“REST 传播者”。
当我认为 Web 应用程序无法进一步发展时,一个新时代似乎正在来临:有状态的持久连接 Web 应用程序。 Meteor 是此类应用程序的出色框架的示例。然后我看到了这个video。在这段视频中,Matt Debergalis 谈到了 Meteor,两者都做得非常出色! 然而,他出于这种目的而降低了 REST API,以支持持久的实时连接。
例如,我非常希望有实时模型更新,但仍然拥有所有 REST 的魅力。 流式 REST API 似乎是我需要的(例如 firehose.io 和 Twitter 的 API),但是关于这种新型 API 的信息很少。
所以我的问题是:
基于 Web 的实时通信是否与 REST 范式不兼容?
(对不起,介绍性文字很长,但我认为这个问题只有在某些情况下才有意义)
【问题讨论】:
【参考方案1】:Web 应用程序的有状态持久 tcp/ip 连接非常棒,只要您不四处走动。
我开发了一个基于 Web 的实时框架,根据我的经验,我发现当我使用基于移动设备的 Web 浏览器时,IP 地址会随着我从一个塔到另一个塔,或者从 wi-fi 到 wi-菲。
当 IP 地址不断变化时,它是持久连接的概念很快就会消失。
实时网络应用框架的架构必须假设连接是瞬态的,并且框架必须实现自己的会话概念,同时与后端的底层 IP 连接不断变化。
一旦在客户端和服务器之间的所有请求和响应中定义并使用了会话,一个会话就基本上具有“网络连接”。现在,人们可以使用 REST 范例开发基于 Web 的实时应用程序。
框架的后端服务器必须智能,以便在 IP 地址进行转换时排队更新,然后在重新建立 tcp/ip 连接时同步。
简短的回答是,'是的,您可以使用 REST 范例来开发基于 Web 的实时应用程序'。
如果你想玩一个,请告诉我。
【讨论】:
REST 告诉我们,每个请求都应该包含所有必要的信息,以便服务器可以是无状态的并且平等地对待每个请求。这是在 REST Web 服务中实现可扩展性的关键特性。没有会议。您是否认为服务器仍然可以通过持久连接(例如 websockets 或 http 长轮询)保持无状态? @miguelcobain,我认为维护持久连接本身的行为使其成为有状态的,即使纯粹是出于性能原因来避免连接设置/拆卸。对我来说,无状态意味着一旦发送响应就绝对没有状态保持 - 不允许例外。对于持久连接,可能会涉及“保持活动”和其他消息,并且服务器必须做一些内务处理,例如关闭最近最少使用的连接等。所有这些都不是无状态服务器所期望的。此外,如果服务器依赖于 cookie,则它们实际上是有状态的。【参考方案2】:我也对这个主题很感兴趣。这篇文章有一些论文链接,这些论文讨论了设计不佳的 RPC 的一些问题:
http://thomasdavis.github.com/2012/04/11/the-obligatory-refutation-of-rpc.html
我并不是说 Meteor 设计不佳,因为我对 Meteor 了解不多。
无论如何,我想我想要两个“世界”中最好的。我想从 REST 以及它提供的所有受约束的通用接口、可寻址性、无状态等中受益。
而且,我也不想在这场“实时”网络革命中落后!这绝对是非常棒的。
我想知道是否没有可以工作的混合方法:
RESTful 端点可以允许客户端进入空间,并按照 HATEOAS 的要求跟踪相关文档的链接。但是,对于资源的“更新流”,“订阅名称”本身可能是一个 URI,当在单个时间点请求中浏览到该 URI 时,例如通过 Web 浏览器的地址栏或 curl,会返回“当前状态”的表示,或带有 href 的链接列表以获取资源的先前状态和/或查询针对对象发生的离散“事件”的方法。
这样,如果您使用实体的“版本 1”声明,然后针对它重播每个事件,您可以将其变异到其“当前状态”,并且此事件可以流式传输到不希望仅仅因为实体的一小部分发生更改而获得完整表示的客户端。这基本上是“事件存储”的概念,在很多 CQRS 信息中都有介绍。
就 REST 兼容而言,我相信这种方法已经完成(尽管我不确定这方面的流式处理),我不记得它是否在本书中 http://shop.oreilly.com/product/9780596805838.do(REST in Practice) ,或者在我听到的 Vaughn Vernon 在 QCon 2010 录制的演讲中的演讲中:http://www.infoq.com/presentations/RESTful-SOA-DDD。
他谈到了类似这样的 URI 设计(我不记得具体了)
host/entity
例子:
host/entity/events/1
他可能也有一些关于历史的东西,完整的时间状态,比如:
host/entity/version/2
Vaughn 最近出版了一本书,《实现领域驱动设计》,从目录来看,它涵盖了 REST 和事件驱动架构:http://www.amazon.com/gp/product/0321834577
【讨论】:
感谢您的链接和您的回答。我相信我和你的情况一样。我不想过时地使用 REST。必须有一种将两者结合起来的方法。见firehose.io。我会仔细评估它是如何解决这个问题的。我觉得值得一看。 在阅读了主页上的基本摘要后,我绝对要去看看 firehose.io。感谢您的链接! 这是一个很好的与 Firehose.io 相关的演示文稿:confreaks.com/videos/…【参考方案3】:我是http://firehose.io/ 的作者,这是一个基于Streaming RESTful API 可以并且应该存在的前提的实时框架。来自项目网站:
Firehose 是一种构建实时网络应用程序的微创方式 无需复杂的协议或从头开始重写您的应用程序。它是 保留客户端 Javascript 模型的简单发布/订阅服务器 通过 WebSockets 或 HTTP 长轮询与服务器代码同步。 它 完全拥抱 RESTful 设计模式,这意味着您最终会得到 构建应用后的一个不错的 API。
我希望这个框架可以防止 Internet 回到 RPC 黑暗时代,但我们会看看会发生什么。我们确实在 Poll Everywhere 的生产环境中使用 Firehose.io,每天向各种不同设备上的人们推送数百万条消息。它有效。
【讨论】:
以上是关于基于 Web 的实时通信与 REST 范式不兼容吗?的主要内容,如果未能解决你的问题,请参考以下文章
基于场景选择微服务的API范式:RESTGraphQLWebhooks和gRPC
基于WebRTC开源框架的实时视频聊天项目,搭建私人实时通信服务