当前位置: 首页 > 科技观察

浅谈RSocket与响应式编程

时间:2023-03-22 10:18:03 科技观察

-RSocket的主要特点首先,RSocket是一种高效的二进制网络通信协议,可用于多种场景。其次,RSocket是响应式的激进捍卫者,激进到连API都与响应式无缝结合。1四种通信方式FireAndForgetFireAndForget立即发送一个请求,而不发送对该请求的响应消息。适用于监控埋点,日志上报等,这种场景不需要回执,丢掉几个请求无伤大雅。RequestResponseRequestResponse请求者发送请求消息,响应者收到请求后返回响应消息。传统的HTTP就是典型的RequestResponse。StreamRequestStream请求者发送一条请求消息,响应者返回N条响应消息。传统的MQ就是一个典型的RequestStream。通道RequestChannel创建一个通道上下文,双方可以在其中相互发送消息。IM是一个典型的RequestChannel通信场景。2双向通信Bi-DirectionalRSocket的客户端连接到服务器。此过程称为设置。连接成功后,会约定发送和接收消息的方向逻辑:客户端向服务器发起请求时,发送的请求ID始终为奇数。服务器向客户端发起请求时,由于奇偶校验决定方向的特性,发送的请求ID总是偶数。与传统的HTTP请求不同,RSocket可以进行双向请求。3其他二进制协议,紧凑高效的多路复用基于Frame的反压,兼容ReactiveStreams语义灵活的传输层切换:TCP/UDP/WebSocket等支持Cancel、resumabletransmission、lease等高级特性总结与HTTP相比,RSocket效率更高,支持更多通信场景,不存在队头阻塞问题。与SocketIO这种纯事件框架相比,RSocket的request上下文非常清晰,API也精炼易用。二RSocket的内部实现1框架设计框架(Frame)是RSocket协议消息的最小单元。一个帧由6字节的Header和其余的Body组成,其中4字节的Header表示StreamID,6位表示FrameType,10位用作Flags。车身根据不同的车架类型有不同的结构。常用的带有Payload的frame一般包括Metadata和Data。如果传输层本身不支持分帧特性(比如TCP),那么RSocket会使用3字节的uint24来表示帧长,所以最大帧长为16MB。如果帧超过16MB,RSocket支持帧拆分重组,即拆分成更小的帧,接收端自动重组。2数据载体——有效载荷以帧为单位。一般开发者都会接触到Payload,它类似于HTTP报文,可以是Request也可以是Response。由两个二进制部分组成:Metadata——元数据,类HTTP的headerData——数据,类HTTP的body3Architecture这里是根据笔者在实现Golang版本SDK的基础上整理的架构图,以及Java版本基本相似。传输层将网络二进制流编码和解码为帧。RSocket支持自定义最大FrameSize,默认为16MB。当一帧超出时,会拆成N个小帧,接收时再重新组装。在介绍框架的时候也提到了。此功能称为碎片化。DuplexConnection将Frames转化为Payload,抽象为Request/Responsecontext,负责读写。RSocket将Connection组装成RSocket接口,其中Resumable支持断点续传,也可以在连接断开重连时进行自我修复。个人觉得这个功能有点鸡肋,在弱网环境下还是有一些优势的,但是因为期间会缓存未处理的帧,所以会消耗大量的系统资源。RSocket使用Reactor核心库暴露了4种通信模式,这些模式被抽象成高级API。4怎么玩RSocket的玩法有很多种,传统的RPC不是问题,可以用来IM,有些功能也可以用来做代理或者网络穿透。在物联网场景下,比如小明家里有一台智能空调,小明想通过外面的手机APP来控制空调的开关。如何优雅地描述这个控制问题呢?最精炼的方案是“小明调用空调开关的API”。另外,最经典的玩法就是Broker。Broker类似于一个“软路由”的解决方案,可以让服务的发布和接入变得更加容易。发布一个服务,只需要连接到Broker,调用者可以通过反向请求让Broker透明转发,摒弃传统的注册中心、端口管理等常见的服务管理方式。5关于RSocketBrokerBroker有很多优点。发布服务不需要监听端口,不需要Sidecar,服务注册变得简单,不需要zk,etcd等。LoadBalance变得更简单更安全,没有监听端口很难被攻击。缺点也很多。网络多了一跳,性能上有一定损失。Broker是集中式设计,类似于我们常用的全局Nginx,但是Broker的优雅启动和停止显然要复杂一些,受限于整个Broker集群的瓶颈等。当上帝为你关上一扇门的时候,他会打开一扇窗为你。目前高德实现的FaaS大量采用了基于RSocket架构的Groupbroker,支撑了今年的五一假期,QPS峰值超过20万,平滑零故障。这里笔者也准备了一个用于教学的MiniBroker,演示了两个浏览器在context中调用对方服务的场景。有兴趣的同学可以看看。三响应式编程响应式编程是一个老话题了,它已经无处不在,即使你用Excel总结,本质上也是一种响应式思维。响应式本质上是响应不断变化的数据流。RSocket协议本身以响应性的名义将其扩展到网络级别。1.响应式编程看起来像这样。在日常工作中,难免会引入各种操作和转换:2.ReactiveStreamsJDK推出了响应式标准API。除了Processor,它的核心接口是Publisher/Subscriber/Subscription,非常精致。.Publisher:发布者,负责生产数据。唯一的订阅方法,接收订阅者以开始新的订阅。Subscriber:订阅者,负责订阅消费数据。Subscription:订阅,某个订阅的上下文控制,比如取消,通知获取下N条数据。Spring的Reactor是一个标准的实现,其完整的执行过程如下:创建订阅者,开始订阅Publisher。生成上下文订阅。发布者准备就绪,调用onSubscribe。Publisher开始生成数据。每次成功产生数据回调onNext。当生产失败时,回调onError,结束当前订阅。当所有数据产生后,回调onComplete,结束当前订阅。中间可以随时调用subscription的cancel来取消订阅,或者通过request(n)通知生产接下来的N个元素。这个过程就是背压。由于Java天生的语言优势,非常适合使用RxJava或Reactor等框架,代码逻辑会非常清晰可读。作者在实现Go版本的Reactor时,深刻体会到没有泛型支持的API是多么缺乏表现力,也期待Go2的泛型能够得到改进。四小结RSocket是一个非常有趣的网络协议,它可能不流行,但它解决问题的思路和设计却很让人耳目一新。有兴趣的可以去其官网一探究竟。本文总结了作者在实现RSocketSDK的Go和Rust版本过程中的一些感悟。感兴趣的同学可以查看相关链接。