购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第1章
响应式简介

响应式这个词承担了很多的含义。你可能已经通过搜索引擎检索过这个词并了解其概念。如果你没有,那也不用担心——你为自己省下了很多困惑。有很多与响应式相关的词汇:响应式系统、响应式编程、响应式扩展、响应式消息传输等。每天都有关于这个词汇的新概念出现。所有这些“reactive”都是同样的响应式吗?这些类似的词汇有什么不同吗?

这些是我们将在本章中回答的问题。我们可以悄悄地观看一下响应式场景,以确定并帮助你理解响应式的各种细微差别,包括这些词汇的含义、与之相关的概念,以及这些词汇之间的关系。是的,在不破坏大多数情况下,所有这些“reactive”都是相关的。

正如前言中所指出的,我们使用名词Reactive(带大写字母R)来聚合响应式场景的各个方面,例如,响应式编程、响应式系统、响应式流等。

1.1 响应式是什么

让我们从头开始吧。在这几分钟内忘掉软件和IT,使用老式的方法。如果在牛津英语词典中查找reactive,我们会发现以下定义:

reactive(形容词)

表现出对刺激的反应。1.应对形势而不是创造或控制形势。2.有化学反应的倾向。3.(生理学)显示对特定抗原的免疫反应。4.(疾病或不适)由对某事的反应引起的症状。5.(物理学)与电抗有关。

在这些定义中,有两个与我们的环境相关。第一个定义是对刺激的反应,指的是某种响应。响应式意味着对刺激做出反应,不管这些刺激是什么。子定义1说,响应也是指面对意外和失控的情况。你会在本书中看到,云原生应用程序以及一般的分布式系统都面临着很多这样的情况。虽然这些定义很有趣,但这些定义并不适用于软件。不过我们可以参考这些定义,并针对软件领域制定出新的定义:

6.(软件)对用户事件、请求和故障等外部刺激而做出响应的应用程序。

然而,正如你将在本书中看到的,今天的响应已经超出了这一点。响应式是一种根据事件和流来设计、实现和推理系统的方法。响应式是关于构建响应式、弹性和可伸缩性的应用程序。响应式还涉及通过高效管理资源和通信来利用资源。换句话说,响应式就是设计和构建更好的分布式系统,使其更健壮、更高效。我们称之为响应式系统。

1.2 响应式软件并不是一件新鲜事

但是我们刚刚给出的定义6并不是突破性的。相反,你可能会感觉这些内容似曾相识,不是吗?软件的本质难道不是对用户输入和操作系统信号做出响应吗?当你击键时,软件是如何运行的?它会响应。那么,如果只是普通软件,为什么会有那么多关于响应式的书籍、演讲和辩论呢?请耐心点,还有一点。

但你是对的,响应式并不是什么新鲜事。这个概念其实很早就有了。我们可以在20世纪50年代计算机出现之后就追踪到响应式软件背后的思想基础。第一代计算机DYSEAC(1954年投入使用)已经使用硬件中断作为优化,消除了轮询循环中的等待时间。这台计算机是最早使用响应式和事件驱动架构的系统之一!

对事件做出响应意味着受事件驱动。事件驱动的软件系统接收并生成事件。接收到的事件决定了程序的流程。事件驱动的一个基本方面是异步性:你不知道何时接收事件 。这正是上一节的定义1。你无法计划何时接收事件,也无法控制将接收哪些事件,你需要做好处理这些事件的准备。这就是响应的本质:异步。

1.3 响应式的整体蓝图

从异步和事件驱动的理念出发,出现了许多模式的响应式解决方案。这个蓝图广阔而拥挤。图1-1摘录了这一蓝图并描述了主要事物之间的关系。

但不要忘记我们的目标:构建更好的分布式系统。其他“响应式”在这里帮助我们实施这些系统。

响应式特征,尤其是出现响应式系统的原因来自分布式系统。正如你将在第3章中看到的,构建分布式系统很困难。2013年,分布式系统专家编写了第一版“响应式宣言”( https : //oreil.ly/6z8mt ),并引入了响应式系统概念。

是的,无须应用响应式原则就可以构建分布式系统。响应式提供了一个蓝图,以确保在设计和开发系统时不会忽略任何重要的已知问题。另外,你可以将这些原则应用于非分布式系统。

响应式系统首先是响应式的。即使在高负载或遇到故障时,响应式也必须及时处理请求。为了实现这种响应式,响应式宣言建议使用异步消息传递作为构成系统的组件之间通信的主要方式。你将在第4章中看到这种通信方法如何实现弹性和恢复力,这是固态分布式系统的两个基本属性。本书的目的是向你展示如何用Quarkus构建这样的响应式系统。因此,构建响应式系统是我们的首要目标。

在分布式系统的核心注入异步消息传递并不是没有后果的。你的应用程序需要使用异步代码和非阻塞I/O,即操作系统提供的无须主动等待完成即可将I/O交互排队的能力。(我们将在第4章介绍非阻塞I/O。)后者对于提高资源利用率至关重要,如CPU和内存,这是响应式的另一个重要方面。如今,许多工具包和框架,如Quarkus、Eclipse Vert.x( https://vertx.io )、Micronaut( https://micronaut.io )、Helidon( https://helidon.io )和Netty( https://netty.io )使用非阻塞I/O正是这个原因:用有限的资源做更多的事情。

图1-1:响应式整体蓝图

然而,拥有一个利用非阻塞I/O的运行时并不足以实现响应式。你还需要编写包含非阻塞I/O机制的异步代码。否则,资源利用效益就会消失。编写异步代码是一种范式转变。从传统(命令式)开始, do x; do y; ,现在,将代码塑造为 on event(e)do x; on event(f)do y; 。换句话说,响应式系统不仅是一个事件驱动的架构,而且你的代码也将成为事件驱动的。实现这类代码最直接的方法之一是回调:在接收到事件时注册调用的函数。与futures、promises和coroutines一样,其他所有方法都基于回调,并提供更高级别的API。

你可能想知道为什么电子表格会出现在这个蓝图中。电子表格是响应式的。在单元格中写入公式并(在另一个单元格中)更改公式读取的值时,此公式的结果将更新。单元格对值(事件)的更新做出响应,结果(响应)就是新的结果。是的,你的经理可能是一个比你更好的响应式开发人员!但别担心,这本书会改变这一点。

第5章介绍的响应式编程也是一种编写异步代码的方法。响应式编程使用数据流来构造代码。你观察数据在这些流中传输并对其做出响应。响应式编程提供了一个强大的抽象和API来塑造事件驱动的代码。

但是使用数据流会带来一个问题。如果你有一个快速的生产者直接连接到一个缓慢的消费者,则可能会淹没消费者。正如你将看到的,我们可以在两者之间缓冲或使用消息代理,但想象一下,如果没有这些缓冲区,消费者的信息就会被淹没。这将不利于响应型组织所倡导的响应能力和反脆弱思想。为了帮助我们解决这个特定问题,响应流( https://oreil.ly/5c275 )提出了一种异步、非阻塞的背压协议,消费者向生产者发送信息,告知其可用性。正如你可以想象的那样,这可能不适用于任何地方,因为某些数据源的速度无法降低。

在过去的几年里,响应流的流行度有所增加。例如,RSocket( https://rsocket.io )是一种基于响应流的网络协议。R2DBC( https://r2dbc.io )提出了使用响应流的异步数据库访问。此外,RxJava( https://oreil.ly/QNEOJ )、Project Reactor( https://oreil.ly/eUHAL )和SmallRye Mutiny( https://oreil.ly/QNEOJ )采用了响应流来处理背压。最后是Vert.x( https : //oreil.ly/tznoI )允许将Vert.x背压模型映射为响应流。

我们对响应式蓝图快速概览到此结束。正如我们所说,这个蓝图充满了许多术语和工具,但永远不要忽视响应式系统的总体目标:构建更好的分布式系统。这是本书的重点。

1.4 为什么响应式架构如此适合云原生应用程序

无论是公有云、私有云还是混合云,都将响应式置于聚光灯下。云平台是一个分布式系统,在云平台上运行应用程序时,该应用程序面临着高度的不确定性。应用程序的消息供给可能很慢,也可能很快,甚至会失败。由于网络故障或分区,通信中断很常见。你可能会遇到配额限制、资源短缺和硬件故障。你正在使用的某些服务有时可能不可用,或者被移动到其他位置。

虽然云平台为基础设施层提供了出色的设施,但云平台只解决了一半的问题。另一半问题是关于你的请求。这些问题都需要被设计成分布式系统的一部分。我们需要理解构建云平台系统的另一半问题所面临的挑战。

我们在本书中介绍的响应式原则有助于应对分布式系统和云应用程序固有的不确定性和挑战。相反,云平台不会隐藏这些不确定性和挑战,而是会拥抱这些挑战。

随着微服务和无服务器计算成为突出的架构风格,响应式原则变得更加重要。该原则可以帮助确保你在一个坚实的基础上设计系统。

1.5 响应式不是银弹

与所有事情一样,响应式也有利有弊。这不是一件魔法武器。没有任何解决方案适用于所有地方。

还记得21世纪10年代末的微服务吗?微服务很快变得非常流行,许多组织在微服务可能不太适合的领域实施了微服务。这通常会把一组问题换成另一组问题。与微服务架构非常相似,响应式架构也有其适合领域。响应式在分布式和云应用程序中大放异彩,但在更为单一和以计算为中心的系统中可能会造成灾难。如果你的系统依赖于远程通信、事件处理或高效率,那么“响应式”将非常有用。如果你的系统主要使用进程内交互,每天只处理几个请求,或者是计算密集型的,那么“响应式”只会带来复杂性。

使用“响应式”,你将事件的概念置于系统的核心。如果你习惯了用传统的同步和命令式方式构建应用程序,那么改变为使用响应式可能会很困难。异步化的需求打乱了大多数传统框架。我们正在远离众所周知的远程过程调用(R P C)和HTTP端点。所以,有了这个免责声明,是时候开始我们的旅程了! KJBwAeKduswcdjTJJU9nAn0EOiaaujGjbq2eFPufdIiVUczIE89/qw6tdtbbLxDX

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开