反应式(Reactive)定义

导言

反应式“reactive”这个词近年来出现频率非常高,但提到响应式时常会令人困惑,它被用来指代许多不同的东西。你可能听说过反应式编程(Reactive Programming)、反应式扩展(Reactive Extensions)、反应式流(Reactive Streams)、反应式消息传递( Reactive Messaging)或反应式系统(Reactive Systems)。但是这些术语的真正含义是什么,它们又是如何组合在一起的呢?

本文将尝试给出其中一些关键术语的定义以及它们之间的关联。

反应式编程(Reactive Programming)

反应式编程是一种通过声明性代码构建异步处理管道的编程范式。换句话说, 代码采用异步数据流方式执行,数据在可用时发送给消费者,这种编程范式编写的程序能够实现快速、异步地对状态变化做出反应。

流(stream)是一系列按时间排序的消息(状态更改)。流中可传递三种消息: 值(value某种数据类型)、错误(error)或完成(complete)信号, 程序中需要定义三种消息对应的处理函数, 消息会异步地被对应的函数捕获处理。对流的监听称作订阅(subscribing)。我们定义的函数是观察者(observable)。流是被观察的主题(或“可观察的对象”)。

响应式编程中,可以为任何内容创建数据流,包括:变量、用户输入、属性、缓存、数据结构等。然后可以订阅这些流并进行相应处理。响应式编程还提供了一个出色的函数工具箱,可以方便的对任意流进行组合、创建和过滤处理,例如:

一个流或多个流可以用作另一个流的输入。

两个流可以被合并。

一个流可以被过滤只保留用户感兴趣的事件的流。

一个流映射的数据将数据值可以被映射到另一个新流。

微服务开发中, 有许多模式和工具能够用于实现反应式编程, 他们包括但不限于:

Futures - 在某个操作完成后保存该操作的结果。

Observables - 是一种软件设计模式,其中称为主体的对象维护其依赖项(观察者)列表,并通过调用它们的方法之一来自动通知它们任何事件(状态更改)。

Publish and Subscribe - 发布和订阅模式

Reactive Streams - 是一种编程概念,用于以非阻塞方式处理异步数据流,同时为流发布者提供回压机制, 下文将详细介绍

Reactive Programming Libraries - 反应式编程库(例如RxJavaSmallRye Mutiny

响应式编程这种异步和非阻塞执行特性,使其成为在管理微服务内部组件本地逻辑和数据流转换方面非常有用的技术。

反应式扩展(Reactive Extensions)

Reactive Extensions是响应式编程范式的实现。

Reactive Extensions结合了观察者和迭代器模式以及函数式编程,提供了一个包含在程序中创建、组合、合并、过滤和转换数据流功能的工具箱。

有一些流行的 Java 响应式扩展,例如ReactiveX(包括RxJavaRxKotlinRx.NET等)和BaconJS。由于有多种库可供选择,而且它们之间缺乏互操作性,因此很难选择使用哪一个。为了解决这个问题,Reactive Streams 标准应运而生。

Reactive Streams

Reactive Streams是一项旨在提供标准以统一反应性扩展并处理具有非阻塞背压的异步流处理的标准,包含运行时环境和网络协议。2015年首次创建的 org.reactivestreams API,包含4个接口:Publisher,Subscriber,Subscription,和Processor。RxJava、Reactor、Akka Streams等扩展框架都实现了这些接口。

Java 开发人员希望标准化 JDK 中的响应式流 API,以便 API 可以自由使用,而无需打包任何第三方库。为了满足这些要求,JDK9在 java.util.concurrent.Flow 中提供了响应式流接口,这在语义上等同于org.reactivestreamsAPI。RxJava、Reactor 和 Akka Streams 都实现了 Flow 下的接口。

Reactive Streams 接口包括:

订阅者和发布者(Subscriber and Publisher)。订阅者是一个流观察者。订阅者通过Publisher.subscribe()方法订阅发布者。然后发布者调用Subscriber.onSubscribe传递订阅,以便订阅者调用subscription.request()(处理回压)或subscription.cancel(), 。

订阅(Subscription)。如果订阅者只能处理 4 个数据项,它将通过Subscription.request(4)传递其处理容量。发布者不会发送超过 4 个,除非订阅者请求更多。Publisher通过调用onNext()发布数据项, 如果没有数据项需要发布则调用onComplete()。

处理器(Processer)。处理器是发布者和订阅者之间的中介。它订阅发布者,然后订阅者订阅处理器。

如上所示,Reactive Streams 引入了publishsubscribe的概念,以及一种将它们联系在一起的方法。但是,通常流还需要map、filter、flatMap 和其他类似于java.util.stream中可用于非反应性流的操作。用户通常并不会自己实现响应式流 API,因为它很复杂,而且很难做到正确并通过 TCKs(允许 Java 技术规范的实现者确定实现是否符合 Reactive Streams 的规范的技术兼容性工具包)。因此,需要引入第三方实现库,例如Akka StreamsRxJava,或 Reactor

但是,许多 MicroProfile 企业应用程序开发人员不想或不能使用第三方依赖项,但希望能够操作反应式流。因此,为了标准化流操作,MicroProfile Reactive Streams Operators应运而生提供与java.util.stream相同的操作. 下面是一个使用 Reactive Streams Operators 的例子。

反应式消息传递(Reactive Messaging)

Reactive Streams 规范和MicroProfile Reactive Streams Operators规范为 MicroProfile Reactive Messaging 规范提供了基础。

如上所述,Reactive Streams 是一种使用背压进行异步流处理的规范。它定义了一组最小的接口,以允许将执行此类流处理的组件连接在一起。MicroProfile Reactive Streams Operators 是一个 Eclipse MicroProfile 规范,它建立在 Reactive Streams 之上,提供一组基本的操作符来将不同的反应式组件链接在一起,并对在它们之间传递的数据进行处理。

所述MicroProfile反应消息规范允许应用程序组件之间发生异步通信,从而实现微服务的时间解耦。如果无论通信中涉及的组件何时运行、它们是否已加载或过载,以及它们是成功处理消息还是失败,都能够进行通信,则此时间解耦是必要的。它可以在微服务之间实现更大的弹性,这是反应式系统的一个关键特征。

MicroProfile Reactive Messaging 旨在为消息传递提供轻量级的反应式解决方案,以确保使用 MicroProfile 编写的微服务能够满足反应式架构所需的需求,从而提供一种将事件驱动的微服务连接在一起的方法。

它在应用程序的 bean 上使用带注释的方法(@Incoming和@Outgoing),并通过命名通道(一个字符串/名称指示要使用的消息源或目的地)将它们连接在一起。

反应式系统(reactive system)

反应式编程、反应式流和反应式消息传递都是设计和构建反应式系统的有用工具。

反应式系统是为了描述在系统级别提供响应式和反应式应用程序的架构风格。它旨在使由多个微服务组成的应用程序作为一个整体一起工作,以更好地对周围环境和彼此做出反应,在处理不断变化的工作负载需求时表现出更大的回弹性,并在组件出现故障时表现出更大的弹性。


反应式宣言列出了反应式系统的四个关键高级特征:

即时响应性(Responsive):响应式系统需要在合理的时间内处理请求

回弹性(Resilient):反应式系统必须在面对故障(错误、崩溃、超时等)时保持响应,因此它必须被设计为能够优雅地处理故障

弹性(Elastic):反应式系统必须在各种负载下保持响应——能够向上和向下扩展。

消息驱动(Message Driven):来自反应式系统的组件使用异步消息传递进行交互,以实现松散耦合、隔离和位置透明。

反应式系统的核心是异步消息驱动微服务系统。尽管反应式系统的基本原理看似简单,但构建一个反应式系统还是很有挑战的。通常,每个节点都需要采用异步非阻塞范式、任务并发模型并使用非阻塞 I/O。因此,在设计和构建反应式系统时需要将这些要点放在非常重要的位置。然而,使用 反应是编程范式和反应式扩展有助于提供一个开发模型来解决这些挑战。它们可以帮助确保代码保持可读性和可理解性。

一些开源的反应式框架或工具包包括Vert.xAkkaProject Reactor 等, 这些框架或工具包提供了反应式流规范接口的实现, 可以大大降低我们实施响应式系统的难度。

总结

在本文中,我们试图定义和区分“反应式”可以引用的关键术语,并解释如何将这些规范一起使用以实现非阻塞和反应式系统的设计和构建。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容