文章目录

  • 一、为啥需要响应式程序?
  • 二、响应式编程思想
  • 三、实现响应式编程的探索
  • 四、响应式框架历史和现状
  • 历史
  • 现状
  • 五、响应式编程规范


一、为啥需要响应式程序?

  1. 传统命令式编程,在遇到需要需要外部资源的服务时,会使得当前线程进入阻塞等待。例如Tomcat的Thread Pre Request模型、命令式编程中I/O操作、微服务之间的等待响应延迟。这样的模型难以应对请求压力,容易导致服务丧失即时的响应性,虽然通过限流、熔断、降级、服务隔离等手段可以从架构上提高服务的响应性。但效率低下的问题仍然存在。
  2. 响应式编程是一种新的编程技术,实现了非阻塞式的客户端 / 服务器交互过程,因此可以用来构建高性能的应用程序。对比命令式编程其优势在于
  1. 不使用Thread Pre Request模型,少量线程处理大量请求
  2. 执行I/O操作不再让线程等待
  3. 简化并行调用
  4. 支持背压,让客户端告诉服务端他的处理能力。

二、响应式编程思想

响应式编程,是使用异步、事件驱动构建的非阻塞式应用程序。此类应用程序,仅需少量线程即可横向拓展。支持背压技术,防止生产者压垮消费者。
其设计目标

  1. 响应性(以时序的方式响应)
  2. 健壮性(发生错误也能保证响应性)
  3. 弹性(可以在不同的负载下保持响应性)
  4. 消息驱动(依赖异步消息传递机制)

三、实现响应式编程的探索

实现响应式应用程序基本思想

  1. 使用异步数据流进行编程,流是一个时序事件序列,可以发布三种不同的事件,值、错误、完成信号
  2. 基于观察者模式,监听一个流成为订阅,定义的函数是观察者,流是被观察者

探索过程中发现的问题

  1. 纯拉取模式存在的问题:在早期响应式编程规范未定的时期,所有响应式库的设计思想,都是把数据源从源头推送到订阅者,因为拉取模型会导致数据源存在大量空闲时间,因为其无法预知即将到来的请求数量。并且产生了大量的网络活动,花费大量时间。
  2. **批量拉取模式存在的问题:**批量拉取,解决了频繁的网络请求带来的损耗,但仍然存在问题,1.数据库批量查询数据时,客户端空闲 2.批量数据的发送更加耗时 3.可能会拉取多余的数据
  3. 推送模式流量控制问题:如果使用推送模式生产者消费者处理能力不一致,系统的稳定性仍然无法保障,虽然可以使用无界队列、有界丢弃队列、有界阻塞队列等对其两边处理能力差异进行缓和,但仍然会导致系统过度复杂化,并且需要额外工作来找到这几种模式的平衡。后面响应式流规范提出了背压机制来解决了这一难题。但是Rx 1.0中并不存在背压机制。

四、响应式框架历史和现状

历史

  • 2011年,微软发布.NET响应式拓展,Reactive Extensions 称为ReactiveX 或者RX,它混合了迭代器模式和**观察者模式。**不同之处在于一个是推送模式,一个是基于迭代器的拉模式。RX的基本思想是,事件是数据,数据是事件。
  • 2013年年末,Netflix 的 bench ristensen 和 david karnok在一起制定了响应式流规范Reactive-Streams,官方网址:http://www.reactive-streams.org 规范文档:https:///reactive-streams/reactive-streams-jvm/blob/v1.0.3/README.md
  • 2014年11月 RxJava 1.0发布,是java的ReactiveX实现,很大程度由Netflix 的 bench ristensen 和 david karnok这些大佬创建。

现状

JVM领域,构建响应式系统最知名的框架是,Akka和Vert.x的生态。

  1. Akka 是一个受欢迎的框架,具有大量功能和大型社区。然而,Akka 最初是作为 Scala生态系统的一部分构建的,在很长一段时间内,它仅在基于 Scala 编写的解决方案中展示了它的强大功能。尽管 Scala 是一种基于 JVM 的语言,但它与 Java 明显不同。几年前,Akka 直接开始支持 Java,但出于某些原因,它在 Java 世界中不像在 Scala 世界中那么受欢迎。
  2. Vert.x 框架也是构建高效响应式系统的强大解决方案。Vert.x 的设计初衷是作为Node.js在 Java 虚拟机上的替代方法,它支持非阻塞和事件驱动。然而,Vert.x 仅在几年前才开始具备竞争力
  3. 过去这些年Spring在java应用程序框架中一直占有举足轻重的地位,但是很长时间里它在构建健壮的响应式系统方面存在一些局限性。

五、响应式编程规范

响应式编程规范官网:http://www.reactive-streams.org 响应式编程文档:https:///reactive-streams/reactive-streams-jvm/blob/v1.0.3/README.md 规定:

  1. 规范规定异步组件之间使用背压进行交互
  2. 响应式规范在Java 9中使用Flow API适配,Flow是互操作的规范,不是具体实现。他的语义和响应式流规范一致。
  3. 响应式流规范,可以使用纯粹的阻塞等待,也可以采用纯拉取模型(只在onNext方法中请求新元素),同时支持带有背压控制的混合推拉模型,使用时如果使用纯推模型,只需要请求Long.MAX_VALUE个元素即可。
  4. 响应式流规范中接口
  1. Publisher接口 表示数据流的生产者,或者数据源。提供一个subscribe方法,供订阅者进行注册
  2. Subscriber接口 表示消费者,其包含 onSubscribe 、onNext、onError、onComplete等事件的处理方式的定义。
  3. Subscription接口 表示订阅票据,消费者可以通过该对象联系生产者,消费者在订阅成功的onSubscribe方法中可取得该对象。该对象的request方法用于让订阅者通知发布者随后需要的元素数量,cancel方法让订阅住主动取消订阅
  4. Processor接口 如果实体需要转换进来的项目,并且传递给后续的订阅者那么他既是发布者又是消费者,便可以实现processor接口。