文章目录

  • 一、初识响应式
  • 1、什么是Reactive(响应式)
  • 2、响应式编程(Reactive Programming)的含义
  • 3、响应式编程的特点
  • 4、响应式编程的主要模式
  • 5、响应式编程的核心元素
  • (1)流
  • (2)传播变化
  • (3)声明式
  • 6、响应式宣言
  • (1)起源
  • (2)Responsive(即时响应性)
  • (3)Elastic(弹性)
  • (4)Message Driven(消息驱动)
  • (5)Resilient(回弹性)
  • 二、响应式架构本质
  • 1、事件与消息(Event & Message)
  • 2、消息传递
  • 3、异步/同步
  • 4、消息流程
  • 5、流量控制(flow control)
  • (1)流量控制
  • (2)Buffer - 背压(Back Pressure)
  • (3)Dynamic Push/Pull
  • 6、目标透明
  • 7、定界一致性
  • 三、响应式架构的优点
  • 1、优点:实时响应
  • 2、优点:高效
  • 3、优点:弹性
  • 四、响应式架构模式
  • 1、单一组件模式
  • 2、错误内核模式
  • 3、任其崩溃模式
  • 4、断路器模式
  • 5、Request-Response模式
  • 6、自包含消息模式
  • 7、前进流模式
  • 8、聚合器模式
  • 9、商务握手模式
  • 10、Pull模式
  • 11、托管队列模式
  • 12、丢弃模式
  • 13、节流模式
  • 五、响应式编程的落地
  • 1、响应式规范:Reactive Streams
  • 2、Java9 - Flow
  • (1)概述
  • (2)Flow类流控制组件
  • (3)Publisher
  • (4)Subscriber
  • (5)Subscription
  • (6)Processor
  • (7)代码示例
  • 3、RxJava
  • 4、Reactor & Spring WebFlux
  • 5、Akka
  • 6、Vert.x
  • 参考资料


一、初识响应式

1、什么是Reactive(响应式)

对刺激(请求)进行快速响应。

对事件(event)立即响应。(事件驱动的自然特性使得反应能够立即加载实时,通过避免对共享资源的争用实现可扩展性)

对失败(failure)立即响应。(在任何级别都可以建立一个能够实现失败恢复的弹性系统)

对用户立即响应。(无论工作在何种负载下,都要满足用户对响应时间的要求)

2、响应式编程(Reactive Programming)的含义

响应式编程定义:
响应式编程是声明性代码以构造异步处理管道的范例。
可以针对任何内容创建数据流,包括:变量,用户输入,属性,缓存,数据结构等,监控流,并据此采取不同措施。
响应式编程还可以对任何这些流进行组合,创建和过滤。

3、响应式编程的特点

响应式编程的本质就是在声明时完全指定值的动态行为。(类似回调)
不再关注系统的状态变化,而是随着时间变化的功能。
执行模型监听数据流来自动传播变化。
使用异步数据流进行编程。

4、响应式编程的主要模式

观察者模式:观察流的变化做出响应。

事件驱动模式:流中的事件驱动系统运作。

发布订阅模式:订阅接收数据源的变化。

5、响应式编程的核心元素

(1)流

流,即序列:
时间分布和数量上无限的一系列动态数据集合体一个按时间排序的事件序列
流不是集合,并不存储元素,而是为特定元素提供操作规范。

非可变性:
数据流作为源,具有非可变性。

响应式编程中的数据流都是异步的。

(2)传播变化

观察流的变化:
将流的变化转化为数据/事件

数据/事件:
根据数据/事件,系统作出对应的响应。(绑定事件时就已经绑定了事件的操作)

实时:
相较于命令式编程,响应式编程可以实时反馈系统(流)的变化。

(3)声明式

命令式:
声明式编程的目标是描述希望得到的结果但是并不指定如何获得这种结果。

声明式:
以数据结构的形式来表达程序执行的逻辑。

无步骤:
声明式编程依赖于具体语言或运行环境来完成任务(获得某种结果)但是并不直接指定每个具体的执行步骤。

(参考函数式编程)

6、响应式宣言

(1)起源

更好的利用了硬件特点:多核。

传统的编程方式,是发起一次请求,等你的响应,这样完成一次交互。
响应式是一种全新的架构风格。

响应式宣言定义了四条黄金法则。

响应式架构设计:性能更高更快的架构模式(框架部分后续再完善)_响应式


响应式架构设计:性能更高更快的架构模式(框架部分后续再完善)_响应式编程_02

(2)Responsive(即时响应性)

系统应该对用户的请求即时做出响应。

即时响应是可用性和实用性的基石,而更加重要的是,即时响应意味着可以快速地检测到问题并且有效地对其进行处理。

确保系统为用户提供快速、一致的响应时间以及一致的服务质量。

简化了错误处理、快速有效地处理,并鼓励用户与系统互动。

(3)Elastic(弹性)

系统在不断变化的工作负载之下依然保持即时响应性。

反应式系统可以对输入负载的速率变化做出反应。

设计上不能有中央瓶颈,使得各个组件可以进行分片或者复制,并在它们之间进行负载均衡。

伸缩性使动态系统可以动态增加或减少分配的资源,从而对输入速率的变化做出优雅的响应。

弹性使反应性系统尽可能地节约资源。

(4)Message Driven(消息驱动)

微服务之间的异步消息传递在组件之间建立了边界,有助于确保松散的耦合、隔离和位置透明性。

以此达到隔离和弹性所需的隔离和封闭程度。

异步消息传递还提供了一种将故障委派为消息的方法。

通过对系统中的消息队列进行整形和监视并在必要时施加反压力来实现负载管理,更大的弹性和负载控制。

无阻塞通信方式还确保了消息的接收者仅在活动时才消耗资源,从而降低了系统开销并更有效地利用了资源。

最大程度减少了系统中共享资源的拥塞,这是可伸缩性,低延迟和高吞吐量的最大障碍之一。

(5)Resilient(回弹性)

系统在出现失败时依然能保持即时响应性,每个组件的恢复都被委托给了另一个外部的组件,此外,在必要时可以通过复制来保证高可用性。因此组件的客户端不再承担组件失败的处理。

确保系统在出现故障时保持响应能力。

通过复制、隔离和委派的组合使用来实现的。

二、响应式架构本质

1、事件与消息(Event & Message)

回调是用于响应某种事件的过程,回调都是与事件生产者绑定的

消息系统提供了一种方式能够发送消息给某个 特定的接受者,由接收者处理消息并做出响应。

消息天然可以替代事件,事件在系统中的传播可以被视为消息沿着处理单元链的转发。

对比起来,消息驱动的系统,更灵活,耦合度更低。

2、消息传递

在系统中某种事件被触发,消息绑定了上下文信息被传递。

消息也可以被认定为一种信号量。

生产者将会通知对该消息感兴趣的消费者,消费者消费消息。

3、异步/同步

同步:双方需要准备好同时进行通信。(难以判断系统是超时还是仍然在计算)

异步:发送方可以发送而无需考虑接收方是否准备就绪。

异步,时间和空间上都做到了解耦。

响应式架构,一般都是采用异步的方式。

4、消息流程

消息流程可以对业务流程建模和可视化,以此避免限制可伸缩性或弹性。

消息传递路径要短。

消息尽可能沿一个方向流动(流向数据的逻辑目的地)。

批处理来发送回执消息来保持数据流的精简。

更推荐DDD的方式定义业务流程,并保证消息流程与之一致。

5、流量控制(flow control)

(1)流量控制

流量控制是调整消息流的传输速率以确保接收者不会过载的过程。
消息发送者被通知必须放慢速度时,就说发送者在承受背压

(2)Buffer - 背压(Back Pressure)

在流处理时,生产速度大于下游消费速度,导致消费者的Buffer溢出,就是在承受背压。

主要是用于处理生产者和消费者之间的速度不均衡。

只有设置buffer上限,才会有背压的问题,如果确保生产速度不会将系统搞崩溃,可以取消buffer的上限,这样就不会有背压的问题。(类似线程池的queue)

(3)Dynamic Push/Pull

Subscribe慢:
Pull base back pressure (采用Pull的方式,消费者能消费多少消息就拉取多少)

Subscribe快:
在第一次请求没有收到之前就发出更多请求。
Publisher根据不同Subscribe的情况满足请求。

6、目标透明

位置透明性是一种属性,无论接收者在哪里处理,用于发送消息的源代码看起来都是相同的。(接收者和消费者耦合度很低)

应用程序组件以显式消息传递定义的统一方式相互交互。

其目标是将本地和远程交互进行通用抽象,并将消息传递的表达进行统一。(只通过消息进行沟通,无论对方在哪里)

将所有消息传递视为可能的远程消息,可以任意重排组件,而不必更改其代码。

7、定界一致性

响应式架构天然分布式,需要建立一种层次结构来处理失败,由父节点来处理子节点的失败,可以向上归因。

将分布式系统拆解为更小的模块,在小模块中实现强一致性,而使系统达成最终一致性。

建议通过DDD的方式将行为和相应的数据集进行切片,也称之为事务边界。

三、响应式架构的优点

1、优点:实时响应

响应式应用程序是实时的:
让客户有实时协作的功能,应用与使用者建立一个开放的和持续的对话,通过响应获得互动体验。
更有效率,长效连接,具备解决问题和完成任务的协作性。
即使存在故障也能尽快响应,如果应用程序在长时间不做出回应,称为延迟,这个系统实际是不可用的。

2、优点:高效

响应式编程大部分都是函数式编程非阻塞的异步操作;等待方法执行转变为发送消息;充分利用多核心CPU的能力提高效率、降低延迟。

3、优点:弹性

故障应对:
应用程序对失败高度宽容,并在运行时能自动修复。

隔离失败:
设置故障隔离点,防止级联故障的经典问题。

消息驱动的松耦合:
消息发送方和接收方均可独立变化,彼此影响影响至最低。

四、响应式架构模式

1、单一组件模式

问题:
系统执行多个功能或它执行的功能非常复杂,需要分解为不同的组件。

模式描述:
由SRP(单一职责原则)派生出来的,每个组件尽量只做一件事,并将此事做到完备。
将一个大问题分解成一组较小的问题,分而治之。
以递归的方式不断地重复划分应用责任。
将组件和层次结构切分到所需的粒度(恰当的粒度,不大不小)。

2、错误内核模式

问题:
响应式架构是具备分层故障处理的能力,如果主管组件发生故障,其所有下属将受到后续重新启动的影响,如何将所有内容重置为已知状态,并保证不丢失中间更新。

模式:
在监督层次结构中,在将风险操作委派给叶子时,将重要的应用程序状态或功能保持在根目录附近。
将系统操作约束集成到基于责任的问题分解中。

适用范围:
系统由具有不同可靠性要求的组件组成。
组件的故障概率和故障严重性不尽相同。

3、任其崩溃模式

问题:
如果程序中某些组件有一些很少见的错误,一旦发生,将阻碍整个系统的运作。

模式:
每当检测到组件有故障时,不修复其资源和数据,直接重新启动,释放其占用的所有资源。(定时重启:起搏器模式;检测故障重启)
在新实例中,不会存在任何脏数据或故障积累,因为系统再次从已知的正确状态开始。

依赖:
心跳检测 - 要应用该模式必须先发现故障,然后才能采取行动,上级组件需要发送虚拟请求,其唯一目的是查看下属是否仍然正常工作。由于其规律和重要的性质,这些被称为心跳。
主动故障信号 - 组件可以处理其内部错误,并将这种错误上报。

4、断路器模式

问题:
当系统中部分组件失效时,如何保证整体系统的大部分功能不受影响。

模式:
在长时间故障条件下中断与用户的连接,保护服务。
在响应式架构中,当消息接收者过载或以其他方式失败时,从一个组件到下一个组件的请求流可能会被故意中断。
接收者从可能的负载引起的故障中恢复。
发件人决定请求将失败,而不是浪费时间等待答复。

适用范围:
此模式适用于两个分离组件 通信的情况,如果故障(预见或意外)不会向上下游传递并感染和减慢其他组件的速度。

5、Request-Response模式

问题:
考虑两个组件A和B,其中A知道B的地址,但B不知道A。这是客户端 - 服务器设置的原型初始条件,其中客户端需要采取第一步 - 服务器不能知道哪些客户端在任何给定时间需要其服务功能。

模式:
在请求中包含回信地址以接收响应。
请求者使用已知的目标地址将请求发送给响应者。
响应方使用相应请求中包含的地址信息向请求者发送响应。

适用范围:
这种模式无处不在,而且理所当然地如此 - 提出请求,需要响应才能得出结论,表明该请求已收到或已执行。

6、自包含消息模式

问题:
消息传播的上下文在哪里保存最合适。

模式:
每个消息将包含处理请求以及了解其响应所需的所有信息。
请求包含处理它所需的所有内容,因此在发生故障后,它完全足以重新处理它,无需系统从头恢复。

适用范围:
希望会话协议保持尽可能简单且会话过程不维护上下文状态。
不应用此模式的主要原因是状态量大于合理的传输量。

7、前进流模式

问题:
如何避免在使用其他模式或类库时引入到不必要的访问开销。
(避免过度设计)

模式:
减少中间环节,尽可能让信息和消息直接流向目的地。

适用范围:
使用前进流来优化整体资源消耗或响应等待时间需要参与服务以允许这些快捷通道。

8、聚合器模式

问题:
如果在一个服务中,需要依赖于很多外部服务,如何尽可能地降低整体延时。

模式:
如果所需多个外部服务之间互相无依赖关系,则可并发进行请求,再汇总结果。
如果需要多个服务响应来计算服务调用的结果,创建一个临时聚合器来聚合多个请求/响应对的结果。

适用范围:
聚合器模式适用于一次计算依赖于多个外部组件参与的场景。

9、商务握手模式

问题:
如何尽可能地让跨组件的消息传递更可靠。

模式:
该模式也称为可靠交付模式。
在消息中包括标识/或排序信息,并继续重试直到收到确认。

适用范围:
适用于必须可靠地传达和处理请求的地方。
在命令不能丢失的情况下,如果机器有故障的可能,可能需要将消息持久化。

重要的三大基础功能:消息要有标识、接收方要有确认、消息发送方要有重发功能。

10、Pull模式

问题:
在响应式系统中,一个挑战是如何平衡消息的生产者和使用者之间的关系。

模式:
让消费者向生产者请求批量数据,而非多次单条请求。
当生产者比消费者快时,系统以Pull模式运行,消费者在每次提出请求时都会从生产者那里批量提取数据。
当生产者比消费者慢时,系统以Push模式运行,生产者不需要等待消费者的请求,而是直接将数据推送到消费者。

以此构成一系列相关组件之间的流量控制关系。通过有无工作需求,消费者将其瞬时加工能力告知生产者,以此实现了一个非阻塞的异步通道,通过该通道可以沿数据处理链传输背压。

11、托管队列模式

问题:
如何处理由于速度差异所导致的系统暂停,进而导致的消息堆积。

模式:
管理一个显式输入队列,并根据其输入级别来进行响应。
在处理引擎中,消息的短脉冲交替出现,这些突发可以通过使用缓冲区来平滑,这些缓冲区允许数据即使在短背压情况下也能够保持流动。
缓冲区临时保存消息,同时记住其顺序的队列,我们称它们为托管队列。

适用范围:
一般在调节背压的域中(例如,通过使用拉模式),缓冲区通常具有平滑突发的主要功能。

12、丢弃模式

问题:
当用户请求已经超过系统能力时,系统应该如何应对。

模式:
丢弃请求比无法控制地失败更可取。(类似服务降级)
只能在指定的条件下提供降级的功能,并且服务应该预见到一个机制,一旦达到这个条件,就启动降级功能,以便保护整体系统资源。

适用范围:
在系统过载期间,希望通过放弃处理一部分请求,而让整体系统能够逐渐恢复到正常状况。

13、节流模式

问题:
如果作为生产者,在生产力超过消费力时该如何控制。

模式:
根据与其他服务的约定来限制服务自身的输出率。
限制模式实现服务协作,其中用户还通过承诺不超过给定速率来保护服务。

适用范围:
处理可能产生背压的场景。

五、响应式编程的落地

1、响应式规范:Reactive Streams

起源:
为了统一各种不同响应式编程库的设计,产生了reactive-streams。
一种标准化技术(基于发布-订阅协议),用于异步、顺序和强制非阻塞回压力处理潜在的不受约束的数据流。

由Netflix、RedHat、Twitter、Lightbend定义了四个相互关联的接口,表示任何反应流实现必须提供的功能集。

第三方库实现,包括Akka流(Lightbend)、Reactor(Pivot)、RxJava(Netflix)和Vert.x(RedHat)

2、Java9 - Flow

(1)概述

在java.util.concurrent.Flow包下:

FlowAPI与Reactive Streams Specification相对应。

该类仅包含四个内嵌接口用于遵循Reactive Streams标准的响应式编程的pub-sub模型。

响应式架构设计:性能更高更快的架构模式(框架部分后续再完善)_响应式_03

(2)Flow类流控制组件

Publisher是无数个顺序事件的提供者。
Publisher允许Subscriber将自己注册为Publisher发出的事件的侦听器。
Publisher和Subscriber之间的流控制由Subscription管理。

(3)Publisher

Publisher<T>
订阅者收到的内容(和相关控制消息)的生产者。
发布者是流中事件T的来源。
发布者将数据流异步发布给注册的订阅者。
Publisher确保每个订阅的Subscriber方法严格按照顺序调用。

(4)Subscriber

Subscriber<T>
消息的接收者。
订阅者是发布者生产的数据/事件的使用者。
调用Subscriber的方法是严格按顺序的。

(5)Subscription

Subscription
消息控件链接了发布者和订阅者。(可以管理Publisher和Subscriber的关联关系,相当于一个中间的桥梁)
Subscriber通过在Publisher中调用“工厂方法”来subscribe,该方法将产生一个能开启一个新的流的Subscription。

(6)Processor

Processor<T, R>

既可以充当Subscriber又可以充当Publisher的组件。

Processor旨在为Subscriber和Publisher之间添加一些处理能力。

由于Processor可能表示某种转换逻辑,因此这使流水线(streaming pipeline)行为和业务逻辑流更易于理解。

Processor的典型用法可以是可以在自定义运算符中描述的任何业务逻辑,或者可以提供流数据的任何额外功能,等等。

响应式架构设计:性能更高更快的架构模式(框架部分后续再完善)_架构_04

(7)代码示例

响应式编程详解,带你熟悉Reactor响应式编程

3、RxJava

4、Reactor & Spring WebFlux

响应式编程详解,带你熟悉Reactor响应式编程

5、Akka

6、Vert.x

参考资料

响应式编程详解,带你熟悉Reactor响应式编程

Spring-WebFlux使用,一文带你从0开始学明白Spring-WebFlux,学明白响应式编程