搜索
首页Javajava教程为什么我们从代码中放弃反应式系统架构?

本文探讨了我们在软件项目中放弃反应式架构的决定。我们将深入研究反应式系统的核心原则、非阻塞 I/O 的好处以及反应式方法所面临的挑战。

理解响应式架构风格

Reactive 包含一系列旨在构建响应式分布式系统和应用程序的原则和指南,其特点是:

  1. 响应能力:即使在重负载下也能够快速处理请求。
  2. 弹性:能够以最短的停机时间从故障中恢复。
  3. 弹性:可以通过相应地扩展资源来适应不断变化的工作负载。
  4. 消息驱动:利用异步消息传递来增强容错能力并解耦组件。

反应式系统的一个主要好处是它们使用非阻塞 I/O。这种方法避免了 I/O 操作期间阻塞线程,允许单个线程同时处理多个请求。与传统的阻塞 I/O 相比,这可以显着提高系统效率。
在传统的多线程中,阻塞操作对优化系统提出了重大挑战(图 1)。消耗过多内存的贪婪应用程序效率低下,并且会惩罚其他应用程序,通常需要请求额外的资源,如内存、CPU 或更大的虚拟机。

Why we discarded Reactive systems architecture from our code?

图 1 – 传统多线程


I/O 操作是现代系统不可或缺的一部分,有效管理它们对于防止贪婪行为至关重要。反应式系统采用非阻塞 I/O,使少量的操作系统线程能够处理大量并发 I/O 操作。

反应式执行模型

虽然非阻塞 I/O 提供了巨大的好处,但它引入了一种不同于传统框架的新颖的执行模型。响应式编程的出现就是为了解决这个问题,因为它可以缓解阻塞操作期间平台线程空闲的低效率问题(图 2)。

Why we discarded Reactive systems architecture from our code?

图 2 – 响应式事件循环


Quarkus 和 Reactive

Quarkus 利用由 Eclipse Vert.x 和 Netty 提供支持的反应式引擎,促进非阻塞 I/O 交互。 Mutiny 是使用 Quarkus 编写反应式代码的首选方法,它采用事件驱动范例,其中反应由接收到的事件触发。

Mutiny 提供两种事件驱动和惰性类型:

  1. Uni: 发出单个事件(一项或失败),适合表示具有零个或一个结果的异步操作。
  2. Multi: 发出多个事件(n 个项目、一个失败或一个完成),表示项目流,可能是无限的。

响应式的挑战

虽然反应式系统提供了好处,但我们在开发过程中遇到了一些挑战:

  • 范式转变: 响应式编程需要开发人员思维方式的根本转变,这可能具有挑战性,特别是对于习惯命令式编程的开发人员来说。与 Streams API 等辅助工具不同,反应式方法需要彻底改变思维方式。
  • 代码可读性和理解: 反应式代码给新开发人员带来了理解困难,导致破译和理解代码的时间增加。反应式范式带来的复杂性加剧了这个问题。

“事实上,阅读与写作所花费的时间之比远远超过 10 比 1。我们不断地阅读旧代码,作为编写新代码的一部分。...[因此,]使其易于阅读使得写起来更容易。”
Robert C. Martin,《整洁代码:敏捷软件工艺手册》

  • 调试挑战:由于 lambda 封装了大多数代码,使用标准 IDE 调试器调试反应式代码几乎是不可能的。此外,异常期间有意义的堆栈跟踪的丢失进一步阻碍了调试工作。 增加开发和测试工作:由于编写、修改和测试所需的时间,反应式代码固有的复杂性可能会导致更长的开发周期。

这是一个使用 Mutiny 的反应式代码示例来说明其复杂性:

Multi.createFrom().ticks().every(Duration.ofSeconds(15))
    .onItem().invoke(() - > Multi.createFrom().iterable(configs())
    .onItem().transform(configuration - > {
  try {
    return Tuple2.of(openAPIConfiguration,
        RestClientBuilder.newBuilder()
            .baseUrl(new URL(configuration.url()))
            .build(MyReactiveRestClient.class)
            .getAPIResponse());

  } catch (MalformedURLException e) {
    log.error("Unable to create url");

  }
  return null;
}).collect().asList().toMulti().onItem().transformToMultiAndConcatenate(tuples - > {

  AtomicInteger callbackCount = new AtomicInteger();
  return Multi.createFrom().emitter(emitter - > Multi.createFrom().iterable(tuples)
      .subscribe().with(tuple - >
          tuple.getItem2().subscribe().with(response - > {
              emitter.emit(callbackCount.incrementAndGet());

  if (callbackCount.get() == tuples.size()) {
    emitter.complete();
  }
                    })
                ));

}).subscribe().with(s - > {},
Throwable::printStackTrace, () - > doSomethingUponComplete()))
    .subscribe().with(aLong - > log.info("Tic Tac with iteration: " + aLong));

未来展望-Project Loom 及未来

Project Loom 是 Java 生态系统的最新开发项目,有望缓解与阻塞操作相关的问题。通过在不更改硬件的情况下创建数千个虚拟线程,Project Loom 可能在许多情况下消除对反应式方法的需求。

“Loom 项目将杀死响应式编程”
布莱恩·戈茨

结论

总之,我们决定放弃反应式架构风格,采用务实的方法来实现项目的长期可维护性。虽然反应式系统提供了潜在的好处,但它们给我们团队带来的挑战超过了我们特定环境中的这些优势。

重要的是,这种转变并没有影响性能。这是一个积极的结果,因为它表明设计良好的非反应式(命令式)架构可以提供必要的性能,而不会带来与我们案例中的反应式架构相关的复杂性。

展望未来,我们的重点仍然是构建一个代码库,该代码库不仅实用,而且易于所有经验水平的开发人员理解和维护。这不仅减少了开发时间,还促进了团队内更好的协作和知识共享。

在下图中,X 轴 代表我们的代码库在发展过程中不断增加的复杂性,而 Y 轴 则描述了这些开发变化所需的时间。

Why we discarded Reactive systems architecture from our code?

以上是为什么我们从代码中放弃反应式系统架构?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能