Springboot引入Reactor已经有一段时间了,笔者潜伏在各种技术群里暗中观察发现,好像scala圈子的同仁们,似乎对响应式更热衷一点。也许是因为他们对fp理解的更深吧,所以领悟起来障碍性更少一些的原因吧。尽管webflux对于数据库的支持,还不那么完善,也不妨我们试上一试。
首先请允许我引用全部的反应式宣言作为开篇,接下来会介绍webflux整合kafka做一个demo。
反应式宣言
在不同领域中深耕的组织都在不约而同地尝试发现相似的软件构建模式。希望这些系统会更健壮、更具回弹性 、更灵活,也能更好地满足现代化的需求。
近年来,应用程序的需求已经发生了戏剧性的更改,模式变化也随之而来。仅在几年前, 一个大型应用程序通常拥有数十台服务器、 秒级的响应时间、 数小时的维护时间以及GB级的数据。而今,应用程序被部署到了形态各异的载体上, 从移动设备到运行着数以千计的多核心处理器的云端集群。用户期望着毫秒级的响应时间,以及服务100%正常运行(随时可用)。而数据则以PB计量。昨日的软件架构已经根本无法满足今天的需求。
我们相信大家需要一套贯通整个系统的架构设计方案, 而设计中必需要关注的各个角度也已被理清, 我们需要系统具备以下特质:即时响应性(Responsive)、回弹性(Resilient)、弹性(Elastic)以及消息驱动(Message Driven)。我们称这样的系统为反应式系统(Reactive System)。
反应式系统更加灵活、松耦合和 可伸缩。这使得它们的开发和调整更加容易。它们对系统的失败 也更加的包容, 而当失败确实发生时, 它们的应对方案会是得体处理而非混乱无序。反应式系统具有高度的即时响应性, 为用户提供了高效的互动反馈。
反应式系统的特质:
即时响应性: :只要有可能, 系统就会及时地做出响应。即时响应是可用性和实用性的基石, 而更加重要的是,即时响应意味着可以快速地检测到问题并且有效地对其进行处理。即时响应的系统专注于提供快速而一致的响应时间, 确立可靠的反馈上限, 以提供一致的服务质量。这种一致的行为转而将简化错误处理、 建立最终用户的信任并促使用户与系统作进一步的互动。
回弹性:系统在出现失败时依然保持即时响应性。这不仅适用于高可用的、 任务关键型系统——任何不具备回弹性的系统都将会在发生失败之后丢失即时响应性。回弹性是通过复制、 遏制、 隔离以及委托来实现的。失败的扩散被遏制在了每个组件内部, 与其他组件相互隔离, 从而确保系统某部分的失败不会危及整个系统,并能独立恢复。每个组件的恢复都被委托给了另一个(外部的)组件, 此外,在必要时可以通过复制来保证高可用性。(因此)组件的客户端不再承担组件失败的处理。
弹性: 系统在不断变化的工作负载之下依然保持即时响应性。反应式系统可以对输入(负载)的速率变化做出反应,比如通过增加或者减少被分配用于服务这些输入(负载)的资源。这意味着设计上并没有争用点和中央瓶颈, 得以进行组件的分片或者复制, 并在它们之间分布输入(负载)。通过提供相关的实时性能指标, 反应式系统能支持预测式以及反应式的伸缩算法。这些系统可以在常规的硬件以及软件平台上实现成本高效的弹性。
消息驱动:反应式系统依赖异步的消息传递,从而确保了松耦合、隔离、位置透明的组件之间有着明确边界。这一边界还提供了将失败作为消息委托出去的手段。使用显式的消息传递,可以通过在系统中塑造并监视消息流队列, 并在必要时应用回压, 从而实现负载管理、 弹性以及流量控制。使用位置透明的消息传递作为通信的手段, 使得跨集群或者在单个主机中使用相同的结构成分和语义来管理失败成为了可能。非阻塞的通信使得接收者可以只在活动时才消耗资源, 从而减少系统开销。
大型系统由多个较小型的系统所构成, 因此整体效用取决于它们的构成部分的反应式属性。 这意味着, 反应式系统应用着一些设计原则,使这些属性能在所有级别的规模上生效,而且可组合。世界上各类最大型的系统所依赖的架构都基于这些属性,而且每天都在服务于数十亿人的需求。现在,是时候在系统设计一开始就有意识地应用这些设计原则了, 而不是每次都去重新发现它们。
Springboot Webflux
引入springboot官网的一张图来解释Spring webflux和spring mvc的区别:
Spring MVC is built on the Servlet API and uses a synchronous blocking I/O architecture whth a one-request-per-thread model.
Spring MVC 构建在 Servlet API 之上,使用的是同步阻塞式 I/O 模型,什么是同步阻塞式 I/O 模型呢?就是说