首先根据RSocket官网的副标题,RSocket的一句话定义是:
在Reactive Manifesto中对Reactive System的定义是:
- Responsive 只要有可能,系统就会及时地作出反应
- Resilient 系统出现failure时仍然保持响应性,并能够独立恢复
- Elastic 系统在不断变化的工作负载之下依然能保持即时响应性
- Message Driven 异步非阻塞消息驱动架构
RSocket即是基于这些基本需求诞生的一种新型反应式网络协议。RSocket借鉴了很多其他协议发展过程中遇到的问题,然后总结归纳进自己的实践当中。
RSocket当前在工业界应用情况
- Netflix:RSocket同样诞生于微服务老祖Netflix,同样它家出品的微服务框架Spring现在已经集成了RSocket支持响应式的微服务编程
- Facebook:2017年上下开始在一些Facebook production案列中得到运用,今年开始了Thrit RPC和RSocket的集成工作。以后Facebook内部的Thrift会主要基于RSocket实现(于是Thrift也会支持streaming了)。
- 阿里巴巴:集成Dubbo RPC和RSocket,在IOT中运用RSocket Broker
- Netifi: 基于RSocket Broker做微服务的startup,(宣称基于RSocket broker的微服务架构比istio省钱10x)
- 其他:Pivotal, LightBend(原名Typesafe,Scala背后的公司)
(PS:以上所有网上都是可以搜索到的)
今年下半年RSocket作为Reactive Foundation第一个项目,也算正式加入了Linux Foundation。以上三家巨头也都是Reactive Foundation的成员,总的来说,RSocket前景还是很不错的。
下面基于RSocket的一些主要特性分别做一下介绍,并和HTTP之类的常见协议进行比较:
- Multiplexed, Binary Protocol 多路复用的二进制协议
- Bidirectional Streaming 双向流
- Flow Control 流控制
- Socket Resumption 连接恢复
- Message passing 消息传递模型
- Transport independent 与传输层解耦的应用层协议
一、Multiplexed Binary Protocol
现在Multiplexing,Asynchronous,Non-blocking I/O已经被说烂了,基本上就是标配。没有这些连台面都上不了。这些特性意味着什么,拿HTTP的发展历史来比喻是最好不过(于是稍微扯远一下):
从HTTP1.0到HTTP3.0 在传输性能上的进步
- 在HTTP1.0时代,每个HTTP request都要新建一个网络连接。网络连接不能复用
- HTTP1.1时代,一个网络连接仍然在一个时候只能负责一个request,但是整个request/response结束后连接可以得到复用。
- 有一些文章讲到HTTP1.1的核心是pipeline功能,在实际运用中其实不然。pipelining支持一个TCP连接上按照顺序连续发送多个HTTP请求而不需要等待前一个请求的响应,但是它同时要求HTTP response也要按照请求的顺序逐个发送,这对服务器提出了很多要求,而且如果第一个响应很慢会拖累所有的后续响应(pipeling的队头阻塞),所以事实上并没有得到多少运用。即使到今天大部分浏览器仍然是默认关闭HTTP pipelining功能的,所以说HTTP1.1的主要突破还只是连接复用。
- HTTP2.0是个飞跃,开始支持multiplexing,一个TCP连接上可以同时承载多个request/response,用这种方式替代1.1的pipelining提升HTTP的并行效果,也自然不存在什么队头阻塞了。每一个request/response的信息流,我们把它称作一个HTTP stream。这个时候一个HTTP client对于一个origin,只需要建立一个TCP就够了。(但是multiplexing带来了新的问题)
- 现在HTTP3.0也差不多了。2.0解决了1.1pipelining的队头阻塞问题,但是却无法解决TCP本身的队头阻塞。而因为TCP/IP在内核协议栈中,简直无法升级,于是HTTP选择了QUIC作为新的传输层协议。 QUIC基于UDP,在用户模式中实现了类似TCP的connection oriented的功能同时解决TCP的队头阻塞,自带multiplexing等等。
所以,HTTP/2具有的优点,RSocket都有。另外,RSocket是一个二进制协议,也就是说在一个RSocket连接上传输的消息体对数据格式没有任何要求,应用程序可以为所欲为的压缩数据量的大小。
这样的二进制协议通常来说能给性能带来极大的提升,但是产生的代价是,网络中间件也会因为无法解读消息体中的数据,丧失了在对具体应用流量进行监控,日志和路由的能力。RSocket通过把每个消息体分成data和metadata的方式,在保证高效传输的前提下,提供了暴露少量元数据给网络中间件的能力。
struct Payload {
iobuf metadata;
iobuf data;
};