SpringOne平台华盛顿大会上宣布的RSocket是一个新的、语言无关的第七层应用网络协议。它是一个双向、多路复用、基于消息、基于反应流回压的二进制协议。它是由Facebook、Netifi和Pivotal等开发的,有Java、JavaScript、C++和Kotlin实现。该协议是专门为反应式应用程序设计的,这类应用程序基本上都是非阻塞的,并且常常(但并不总是)与异步行为相结合。使用反应式回压,即发布者不能向订阅者发送数据,直到该订阅者表明它已就绪,这是它与“async”的一个关键区别。
Cloud Foundry Java Experience团队负责人Ben Hale说,“我个人认为,反应式编程是Java高效应用的下一个前沿。”Hale指出,反应式编程有两个主要障碍——数据访问和网络。RSocket旨在解决后一个问题,而R2DBC用于解决前一个问题。
在微服务风格的应用程序中,HTTP是广泛使用的通信协议。Pivotal Reactor项目负责人Stephane Maldini在阐述开发新协议的原因时指出,HTTP是为一个完全不同的世界而设计的。
我们有iphone和Android手机,我们等听通知,所以我们不需要通过请求来得到回复,我们可以得到多个回复,而不需要与设备进行交互。我们在运动时还会使用智能手表,它与后台服务器交互,提供统计信息。我们有智能助手与后端服务器交互。所有这些交互模型都是我们所说的连接体验的一部分。HTTP真不是为此而设计的。
Maldini认为,HTTP的一个重要问题是,它把所有的职责都放在客户端,用重试逻辑、超时、断路器等来处理不同类型的错误。使用反应式架构构建的应用程序可以提高效率并有很好的扩展性,但Maldini认为,“反应式支持停留在应用程序边界上”。
RSocket与HTTP的不同之处在于它定义了四种交互模型:
- 即发即忘(Fire-and-Forget):这是对请求/响应的优化,在不需要响应时非常有用,比如用于非关键事件的日志记录。
- 请求/响应:当你发送一个请求并接收一个响应时,就像HTTP一样。即使在这种情况下,该协议也比HTTP更具优势,因为它是异步且多路复用的。
- 请求/流:类似于返回集合的请求/响应,集合将以流的方式返回,而不是等到查询完成,例如,发送一个银行帐号,使用一个实时的帐户事务流进行响应。
- 通道:允许任意交互模型的双向消息流。
基于消息意味着该协议可以在单个连接上支持多路复用。此外,与TCP一样,它是真正双向的,一旦客户端初始化了到服务器的连接,连接双方就变得彼此对等——实际上,服务器可以从客户端请求数据。
RSocket还支持以消息为单位的流量控制。在主题演讲中,Facebook工程师Steve Gury表示:
当你发送消息时,你同时得指定你能够满足多少响应,服务器必须满足这个约束,但是,当我处理完这些响应后,我可以要求更多的响应。RSocket也是在整个链上工作,因此,如果你链接多个RSocket连接,那么流控制也将作用到端到端。
实际上,正如Hale在当天晚些时候的后续会议中所说的那样,RSocket解决的问题是跨进程回压,即网络上的回压。
我可以保证,我不会请求超出进程内部处理能力的数据,但是当我不得不调用服务网格中的另一个微服务时会发生什么。我如何保证,它不会突然出现一大堆数据,也不会试图给我发送所有的数据。
RSocket是传输无关的,支持TCP、WebSocket和Aeron UDP协议,并支持无语义损失的混合传输协议——回压和流量控制仍然有效。
它还支持连接恢复。当你建立RSocket连接时,你可以指定前一个连接的ID,如果流仍然在服务器的内存中,则你可以继续消费你的流。
在前面提到的演讲中,Hale给出了更多关于协议工作原理的细节。如上所述,它是一个消息驱动的二进制协议。Hale说:“我们的想法是,在给定网络连接的情况下,请求者-响应者交互被分解成一组离散的帧。这些帧中的每一个都封装了某种信息。”帧是二进制的,而不是像JSON或XML那样是人类可读的,对于机器对机器的通信,这显然更有效率。与所有消息传递协议一样,有效负载只是字节流,因此可以是你想要的任何内容,包括XML或JSON。
在Facebook上,使用RSocket的一个地方是一个叫LiveServer的服务,它负责响应一个在线查询,这个查询可以视为一个GraphQL订阅。服务器使用数据进行响应,同时还将提供一个未来更新的流。