Getting started with reactive systems 开启响应式系统,From IBM

The term "reactive" has become a fairly loaded and sometimes confusing term, which is used to refer to many different things. You might have heard of reactive programming, reactive extensions, reactive streams, reactive messaging or reactive systems. But what do these terms really mean and how do they all fit together?

In this article, we will attempt to define some of these key terms and where they fit together. However, it is worth noting that this is an area that is constantly developing and can be highly opinionated due to many of these terms relating to concepts or specifications as opposed to implementations.

Then, we'll then dive deeper into reactive systems (an architectural style that enables applications composed of multiple microservices to work together as a single unit in order to better react to their surroundings and one another). Reactive systems are already in use in a wide variety of industries and use cases. But, how is this defined, and what makes a reactive system truly reactive? And, importantly, how can we implement this in our own applications?

“响应式”这个术语已成为一个相当复杂且有时令人困惑的词汇,它被用来指代许多不同的事物。您可能听说过响应式编程、响应式扩展、响应式流、响应式消息或响应式系统。但这些术语的真正含义是什么?它们之间又是如何相互关联的?

在本文中,我们将尝试定义其中一些关键术语及其关联性。但值得注意的是,这是一个不断发展的领域,由于许多术语涉及的是概念或规范而非具体实现,因此可能存在高度主观的解读。

接下来,我们将深入探讨响应式系统(一种架构风格,使由多个微服务组成的应用程序能够作为一个整体协同工作,从而更好地对周围环境及彼此作出反应)。响应式系统已在众多行业和应用场景中得到广泛应用。但究竟如何定义响应式系统?什么使一个系统真正具备响应式特性?更重要的是,我们如何在自己的应用程序中实现这种架构?

Defining the term "reactive"


Let's break down all these terms: reactive programming, reactive extensions, reactive streams, reactive messaging and reactive systems.

让我们来分解所有这些术语:响应式编程、响应式扩展、响应式流、响应式消息和响应式系统。

Reactive programming


In technical terms, reactive programming is a paradigm in which declarative code is issued to construct asynchronous processing pipelines. In other words, it's programming with asynchronous data streams that sends data to a consumer as it becomes available, which enables developers to write code that can react to these state changes quickly and asynchronously.

A stream is a sequence of ongoing events (state changes) ordered in time. Streams can emit three different things: a value (of some type), an error, or a "completed" signal. The events are captured asynchronously, by defining a function that will execute when a value is emitted, another function when an error is emitted, and another function when 'completed' is emitted. "Listening" to the stream is called subscribing. The functions we are defining are observers. The stream is the subject (or "observable") being observed.

用技术术语来说,响应式编程是一种通过声明式代码构建异步处理管道的范式。换句话说,它采用异步数据流进行编程,当数据可用时就将其发送给消费者,这使得开发者能够编写快速异步响应状态变化的代码。

数据流是按时间顺序排列的持续事件(状态变化)序列。流可以发出三种内容:某种类型的值、错误或"完成"信号。通过定义三种函数来异步捕获这些事件:当值发出时执行的函数、错误发出时执行的函数,以及'完成'发出时执行的函数。"监听"数据流的行为称为订阅。我们定义的这些函数就是观察者。而数据流则是被观察的主体(或称"可观察对象")。

Using reactive programming, you can create data streams for anything, including: variables, user inputs, properties, caches, data structures, and so on. These streams can then be observed and actions can be taken accordingly. Reactive programming also provides a fantastic toolbox of functions to enable the combination, creation, and filtering of any of these streams, such as:

使用响应式编程,你可以为任何事物创建数据流,包括:变量、用户输入、属性、缓存、数据结构等。然后可以观察这些流并相应地采取行动。响应式编程还提供了一套极佳的工具函数集,用于组合、创建和过滤这些数据流,例如:

— A stream or multiple streams can be used as an input to another stream.
— You can merge two streams.
— You can filter a stream to get another one that has only those events you are interested in.
— You can map data values from one stream to another new one.

— 一个或多个流可作为另一个流的输入。
— 你可以合并两个流。
— 你可以对流进行过滤,从而获得仅包含你感兴趣事件的新流。
— 你可以将数据值从一个流映射到另一个新流中。


There are many patterns and tools that can be used to enable reactive programming within microservices. They include:

Futures, which is a promise to hold the result of some operation once that operation completes.
Observables, which is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any events (state changes), usually by calling one of their methods.
Publish and Subscribe
Reactive Streams, which we describe in more detail later in this article, is a programming concept for handling asynchronous data streams in a non-blocking manner while providing backpressure to stream publishers
Reactive Programming Libraries, which is used for composing asynchronous and event-based programs (such as RxJava and SmallRye Mutiny)

在微服务中实现响应式编程可采用多种模式和工具,包括:

Futures(期货) - 代表异步操作完成后返回结果的承诺
Observables(可观察对象) - 一种设计模式:当主体对象状态变化时,自动通知所有注册的观察者对象
发布/订阅模式
Reactive Streams(响应式流) - 后文将详细说明,该编程概念支持非阻塞式异步数据流处理,同时为流发布者提供背压机制
响应式编程库 - 用于编写基于事件和异步的应用程序(例如RxJava和SmallRye Mutiny)


Reactive programming can be a useful implementation technique for managing internal logic and data flow transformation locally within components like microservices (inter components), through this asynchronous and non-blocking execution.

响应式编程是一种实用的实现技术,通过这种异步非阻塞的执行方式,可有效管理微服务等组件内部(组件间)的逻辑与数据流转换。

Reactive extension


Reactive programming deals with data flow and automatically propagates changes via the data flow. This paradigm is implemented by Reactive Extensions.

Reactive extensions enables imperative programming languages to compose asynchronous and event-based programs by using observable sequences. In other words, it enables your code to create and subscribe to data streams named observables. Reactive extensions combine the observer and iterator patterns and functional idioms to give you a sort of toolbox, enabling your application to create, combine, merge, filter, and transform data streams.

There are a few popular reactive extensions for Java, such as ReactiveX (which includes RxJava, RxKotlin, Rx.NET, and so on) and BaconJS. With a variety of libraries to choose from and a lack of interoperability among them, it can be hard to choose which one to use. To solve this issue, the Reactive Streams initiative was established.

响应式编程处理数据流,并通过数据流自动传播变更。这种范式通过响应式扩展库实现。

响应式扩展使得命令式编程语言能够通过可观察序列来组合异步和基于事件的程序。换句话说,它让您的代码能够创建和订阅名为"可观察对象"的数据流。响应式扩展结合了观察者模式、迭代器模式和函数式编程范式,为您提供了一套工具箱,使应用程序能够创建、组合、合并、过滤和转换数据流。

Java领域有几个流行的响应式扩展库,例如ReactiveX(包含RxJava、RxKotlin、Rx.NET等)和BaconJS。由于可选库众多且相互之间缺乏互操作性,选择使用哪个库可能很困难。为解决这个问题,Reactive Streams计划应运而生。

Reactive streams


Reactive Streams is an initiative that was created to provide a standard to unify reactive extensions and deal with asynchronous stream processing with non-blocking backpressure, which encompasses efforts aimed at runtime environments as well as network protocols. The org.reactivestreams APIs, first created in 2015, contain 4 interfaces: Publisher, Subscriber, Subscription, and Processor. The extension frameworks such as RxJava, Reactor, Akka Streams all implement these interfaces.

Java developers wanted to standardize the reactive streams APIs in the JDK, so that the APIs could be freely available without having to package any third party libraries. To meet these requests, JDK9 made the reactive streams interfaces available under java.util.concurrent.Flow, which is semantically equivalent to org.reactivestreams APIs. RxJava, Reactor, and Akka Streams all implement the interfaces under Flow.

响应式流是一项旨在为异步流处理提供统一标准的倡议,它通过非阻塞回压机制协调运行时环境与网络协议。最初于2015年制定的org.reactivestreams规范包含四个核心接口:发布者(Publisher)、订阅者(Subscriber)、订阅关系(Subscription)和处理者(Processor)。RxJava、Reactor及Akka Streams等主流响应式框架均实现了这些接口。

Java开发者期望将响应式流API标准化集成至JDK,从而无需依赖第三方库即可使用。为满足这一需求,JDK9在java.util.concurrent.Flow包下提供了语义等同org.reactivestreams的接口实现。目前RxJava、Reactor和Akka Streams均已适配Flow包下的接口规范。

The Reactive Streams interfaces are:

Subscriber and Publisher. The Subscriber is a stream Observer. A Subscriber subscribes to a Publisher via the method Publisher.subscribe(). Then the Publisher calls Subscriber.onSubscribe to pass over the Subscription, so that the Subscriber calls subscription.request(), which takes care of back pressure or subscription.cancel().

订阅者与发布者。订阅者是流的观察者。订阅者通过Publisher.subscribe()方法订阅发布者。随后,发布者调用Subscriber.onSubscribe传递Subscription对象,使得订阅者能够调用subscription.request()处理背压问题,或调用subscription.cancel()取消订阅。

Subscription. If the subscriber is only capable of handling 4 items, it will pass its capacity via Subscription.request(4). The publisher will not send more than 4 unless the subscriber requests more. The Publisher invokes onNext() when an item is published or onComplete() if no item is to be published.

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

Processor. A processor is an intermediary between Publisher and Subscriber. It subscribes to a Publisher and then a Subscriber subscribes to Processor.

As shown above, Reactive Streams introduces the concepts publish, subscribe, and a way to plumb them together. However, the streams typically need to be manipulated by maps, filters, flatMaps, and more (similar to java.util.stream, which is available for non-reactive streams). Users are not meant to implement reactive streams APIs directly, as it is complicated and it is difficult to get it right and pass TCKs (Technology Compatibility Kit, a suite of tests, tools, and documentation that allows an implementor of a Java technology specification to determine if the implementation is compliant with the specification) for Reactive Streams. As a consequence, the implementations have to be provided by third party libraries such as Akka Streams, RxJava, or Reactor.

However, many MicroProfile enterprise application developers didn't want to or couldn't use third party dependencies but wanted (needed) to be able to manipulate reactive streams. So, in order to standardize the stream manipulation, MicroProfile Reactive Streams Operators was created to offer the equivalent functionality as java.util.stream. An example of the usage of Reactive Streams Operators is shown below.

如上所述,Reactive Streams引入了发布、订阅的概念以及将它们连接起来的方法。然而,这些流通常需要通过map、filter、flatMap等操作进行处理(类似于可用于非反应式流的java.util.stream)。用户不应直接实现反应式流API,因为这很复杂,且难以正确实现并通过Reactive Streams的TCK(技术兼容性工具包,一套测试、工具和文档,用于确定Java技术规范实现是否符合该规范)。因此,这些实现需要由第三方库(如Akka Streams、RxJava或Reactor)提供。

然而,许多MicroProfile企业应用开发者不希望或无法使用第三方依赖,但又希望(需要)能够操作反应式流。因此,为了标准化流操作,MicroProfile Reactive Streams Operators应运而生,它提供了与java.util.stream相当的功能。下面展示了Reactive Streams Operators的使用示例。

Reactive messaging


The Reactive Streams specification and the MicroProfile Reactive Streams Operators specification provides the basis for the MicroProfile Reactive Messaging specification.

As described above, Reactive Streams is a specification for doing asynchronous stream processing with back pressure. It defines a minimal set of interfaces to allow components that do this sort of stream processing to be connected together. The MicroProfile Reactive Streams Operators is an Eclipse MicroProfile specification which builds on Reactive Streams to provide a set of basic operators to link different reactive components together and to perform processing on the data which passes between them.

反应式流规范与MicroProfile反应式流操作符规范为MicroProfile反应式消息传递规范奠定了基础。

如前所述,反应式流是一套支持背压机制的异步流处理规范。它定义了一组最小接口,使得执行此类流处理的组件能够相互连接。MicroProfile反应式流操作符是Eclipse MicroProfile的一项规范,基于反应式流构建,提供了一组基础操作符,用于将不同反应式组件链接起来,并对流经组件之间的数据执行处理。

The MicroProfile Reactive Messagingspecification allows asynchronous communication to occur between application components, enabling temporal decoupling of microservices. This temporal decoupling is necessary if communication is to be enabled to occur regardless of when the components involved in the communication are running, whether they are loaded or overloaded, and whether they are successfully processing messages or failing. It enables greater resiliency between microservices, which is a key characteristic of reactive systems.

MicroProfile Reactive Messaging was designed to provide a lighter-weight, reactive solution to messaging to ensure microservices that are written using MicroProfile are able to meet the demands required by a reactive architecture thereby providing a way to connect event-driven microservices together.

It uses annotated methods (@Incoming and @Outgoing) on an application's beans and connects them together by named channels (a string/name indicating which source or destination of messages is to be used).

MicroProfile 响应式消息传递规范支持应用程序组件之间进行异步通信,从而实现微服务的时间解耦。这种时间解耦对于确保通信能够发生至关重要——无论参与通信的组件何时运行(处于加载或过载状态),无论它们正在成功处理消息还是发生故障。这种机制增强了微服务之间的弹性,这正是响应式系统的核心特征。

MicroProfile 响应式消息传递的设计目标是提供更轻量级的响应式消息解决方案,确保基于MicroProfile开发的微服务能够满足响应式架构的要求,从而为事件驱动型微服务提供互联机制。

该规范通过在应用程序Bean上使用注解方法(@Incoming和@Outgoing),并通过命名通道(指定消息来源或目标的字符串/名称)将这些方法连接起来实现通信。

Reactive systems


Reactive programming, reactive streams, and reactive messaging are all useful tools to design and build reactive systems.

The term reactive systems was coined to describe an architecture style to deliver responsive and reactive applications, at the system level. It is designed to enable applications composed of multiple microservices working together as a single unit to better react to their surroundings and one another, manifesting in greater elasticity when dealing with ever-changing workload demands and resiliency when components fail. It is based upon the Reactive Manifestooutlined in the following diagram.

响应式编程、响应式流和响应式消息都是设计和构建响应式系统的实用工具。

"响应式系统"这一术语被创造出来,用于描述在系统层面交付灵敏响应型应用程序的架构风格。该架构旨在让由多个微服务组成的应用程序作为一个整体协同工作,从而更好地对环境变化作出反应,并在组件之间实现更高效的互动。这体现在:面对不断变化的工作负载时能展现更强的弹性伸缩能力,在组件发生故障时能保持系统韧性。其设计理念基于下图所示的《响应式宣言》原则。

The Reactive Manifesto lays out four key high-level characteristics of reactive systems:

        — Responsive: a reactive system needs to handle requests in a reasonable time
        — Resilient: a reactive system must stay responsive in the face of failures (errors, crashes, timeouts, etc), so it must be designed to be able to gracefully handle failures
        — Elastic: a reactive system must stay responsive under various loads - being able to scale both up and down.
        — Message driven: components from a reactive system interact using asynchronous message passing to enable loose coupling, isolation and location transparency.


Reactive systems are asynchronous-message-driven systems at their core. Despite the seeming simplicity of the fundamental principles of reactive systems, building one of them can be tricky. Typically, each node needs to embrace an asynchronous non-blocking development model, a task-based concurrency model, and use non-blocking I/O. So, it's important to really consider these points when designing and building your reactive system. However, using Reactive Programming and Reactive Extensions helps to provide a development model to tackle these asynchronous challenges. They can help to ensure your code remains readable, and understandable.

反应式系统的核心是基于异步消息驱动的架构。尽管反应式系统的基本原则看似简单,但构建这样的系统可能颇具挑战性。通常,每个节点都需要采用异步非阻塞的开发模式、基于任务的并发模型,并使用非阻塞I/O。因此,在设计和构建反应式系统时,认真考虑这些要点至关重要。不过,采用反应式编程和反应式扩展能帮助提供应对这些异步挑战的开发模型,它们有助于确保代码保持可读性和可理解性。

Implementing all of this can seem like a fairly daunting task! But, to make this a little easier, there are several open-source reactive frameworks or toolkits available to help, including Vert.x, Akka, and Project Reactor, just to name a few. These frameworks or toolkits provide API implementations that add value on top of other reactive tools and patterns (including the Reactive Streams specification, RxJava, and so on).

实现所有这些可能看起来是一项相当艰巨的任务!但是,为了让事情变得简单一些,市面上有多个开源响应式框架或工具包可以提供帮助,包括Vert.x、Akka和Project Reactor等。这些框架或工具包提供了API实现,在现有响应式工具与模式(包括Reactive Streams规范、RxJava等)的基础上进一步创造价值。

Build Reactive microservices today with Open Liberty

There are many different ways to implement a reactive system. Each framework achieves concurrency, parallelism, resiliency, and messaging in a variety of ways, and interacts with the underlying infrastructure differently. So, it's important to fully understand the capabilities of the implementation you choose.

Reactive Messaging for MicroProfile is an open-source specification that provides asynchronous messaging support based on MicroProfile Reactive Streams. MicroProfile Reactive Messaging provides a very easy-to-use way to send, receive, and process messages, and is well-suited to writing applications that process streams of events. Reactive Messaging uses a model of annotated methods that are connected by named channels. In the blog post "Sending and receiving messages between microservices with MicroProfile Reactive Messaging" (Open Liberty), Andrew Rouse and Gordon Hutchison describe how to send and receive messages between microservices using MicroProfile Reactive Messaging. MicroProfile Reactive messaging, although not an end-to-end reactive solution, enables non-blocking, asynchronous message passing between services, giving them the ability to scale, fail, and evolve independently, and to remain unaffected by each other's availability. MicroProfile Reactive Messaging can be used alongside Open Liberty to create reactive systems.

Try it for yourself and see how you could implement this in your own Java applications, in the Open Liberty reactive service guides.

参  考

https://developer.ibm.com/articles/reactive-systems-getting-started/

https://smallrye.io/smallrye-mutiny/

https://github.com/eclipse/microprofile-reactive-streams-operators/

https://github.com/ReactiveX/RxJava

http://reactivex.io/

http://baconjs.github.io/

https://www.reactive-streams.org/

https://doc.akka.io/docs/akka/current/stream/reactive-streams-interop.html

https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html

https://projectreactor.io/

https://github.com/eclipse/microprofile-reactive-messaging

https://github.com/eclipse/microprofile-reactive-streams-operators

https://github.com/eclipse/microprofile-reactive-messaging

https://www.reactivemanifesto.org/

https://openliberty.io/blog/2019/09/13/microprofile-reactive-messaging.html

// Oracle 相关7篇文章

https://blogs.oracle.com/javamagazine/category/jm-reactive-programming

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值