使用API驱动的微服务来构建可靠的业务流程,成为了许多现代应用程序(比如在线订餐配送、网约车服务、在线金融交易处理、电商订单处理等)的常见做法。然而,这种方法在实际应用中会遇到一些关键挑战,尤其是可靠性和一致性的问题。
这个问题的根源在于可靠性,即一个业务流程的稳定性取决于最脆弱的微服务。一旦同步 API 调用中的某个服务出问题,整个流程就会崩溃。即使每个服务都很可靠,涉及的微服务越多,从头到尾成功执行的概率就越低。
一致性问题通常出现在多步骤流程中途失败时。一些服务调用可能已经成功完成,导致分布式微服务的数据状态不一致。在这种情况下,回滚和手动修复会变得相当复杂。
更好的解决方案是采用一种编排模式,如这里所述,来沿用事件驱动的架构。利用专门的流程服务,通过异步事件编排微服务,可以大大提升可靠性和一致性。即使某些服务暂时中断,流程也可以在它们恢复运行后继续进行,从而在整个过程中保持数据的一致性和完整性。
在这篇文章中,我将探讨如何利用基于事件的编排框架Infinitic,构建稳健、事件驱动的业务流程。我将深入探讨架构模式、工作流实现及部署考量,展示如何以最小的努力实现关键任务应用程序在可靠性和一致性方面取得显著的提升。
基于 API 的服务构建业务流程想要了解事件驱动型应用程序和Infinitic的最新进展并保持前沿?订阅https://infinitic.substack.com,不错过任何消息,确保不错过这个快速发展的领域的任何动态。
使用 API 驱动的微服务来构建可扩展的业务流程是一种非常好的方法。这些流程一般直接从面向客户的应用程序启动,或者如果是定期重复任务,则通常通过计划的 cron 任务来执行。
使用API驱动的服务来构建业务流程
但是,这种常见的模式主要存在两个问题,
可靠性方面的问题你的业务流程依赖于跨多个微服务的同步的API调用,因此变得很脆弱。由于流程依赖于每个服务都能成功响应,任何一个服务出错都会导致整个流程就会中断。随着需要交互的微服务数量增多,整体流程的稳定性就越容易受到影响,因为任何一个环节出错都会影响整体。
例如,如果每个由 API 驱动的微服务具有 99.95% 的可靠性(大约每月有 21 分钟的停机时间,按每天 30 天计算),那么一个使用 10 个微服务的业务流程将具有可靠性为 .9995¹⁰,即 99.5%(大约每月有 3 小时 36 分钟的停机时间,按每天 30 天计算)。
要解决这个问题,你可以为每个微服务增加冗余,但这会增加基础设施的成本,并且并不能从根本上解决这个问题。例如,它不能防止由网络故障引起的问题。
另外,你可以添加一个消息代理(例如RabbitMQ),并将启动业务流程的请求推送到队列。这样即使业务流程实例失败,也会自动重试。虽然这种方法可以帮助解决自动重试问题,但并不能解决以下的一致性问题。
一致性问题当一个业务流程在某些微服务调用成功后失败时,一致性问题就会出现。这可能会使系统处于一种不一致的状态,数据更新分散在不同的服务上。在流程控制器中实现回滚机制很复杂,而且如果控制器本身也失败了,这些机制就无法发挥作用。
总体来说,这种情况通常挺有挑战的,因为在分布式系统中调试并找出差异的原因既复杂又耗时得多,经常需要手动解决。
使用消息中间件: 使用消息中间件,以下将进行介绍和说明。更好的解决方案是采用事件驱动的异步通信模型,使用消息代理。而不是直接在微服务之间推送内存中的 HTTP 请求,服务可以将事件发布到由代理提供的持久消息队列。其他服务在准备好时可以从队列中拉取消费这些事件。这种解耦的消息驱动架构通过在消费前持久化数据,增强了可靠性,防止因停机时间导致的失败。此外,它避免了为了处理峰值负载而需要过度扩展微服务的需求,因为消息代理可以缓冲请求,从而减少成本。
这通常通过使用编排模式(choreography pattern)来实现,这是一种事件驱动架构,其中各个微服务根据其他服务发出的事件相应地采取行动。基于事件的设计解决了可靠性问题(即使某个服务暂时不可用,它在恢复后可以继续执行),并且有助于保持一致性,因为即使在执行过程中遇到临时问题,工作流最终也会完成其任务。
构建一个基于事件交换的服务业务流程,通过服务间事件交换。
这种方法在简单的场景中可能有效,但随着业务流程变得越来越复杂,涉及条件判断、超时和错误处理等,编写代码、维护和观察会越来越困难。
在《我们构建事件驱动应用程序的方式是错误的》这篇文章中,我描述了为什么我更倾向于使用编排模式,这是一种事件驱动系统的替代架构,在这种架构中,有一个专用的工作流服务作为中央编排器,协调处理业务流程的各种微服务。该服务启动流程的执行,管理事件和微服务调用的顺序,并根据需要处理错误或重试操作。编排模式简化了复杂事件驱动流程的开发和维护工作,并且与编舞模式相比,提供了更好的可观察性和控制。
用工作流服务来编排事件驱动的业务流程处理
在之前的文章里,我介绍了我开发的Infinitic框架,该框架能够实现不可分割的事件驱动型应用的集中调度。
图中标注为绿色的关键组成部分如下所示:Infinitic提供了这些关键组成部分。
- 客户端:这是启动和互动业务流程工作流的入口。
- 服务工件:这些是专门负责执行特定服务的工件。每个服务工件可以在 Apache Pulsar 上发布和消费与其服务相关的事件,并处理错误处理。
- 工作流工作者:这些是中心编排组件。它们管理整个业务流程的流程管理,并通过发布和消费事件来协调服务执行。
使用Infinitic构建事件驱动的生产就绪业务流程
目前,Infinitic 使用 Apache Pulsar 作为底层消息系统,。
使用Infinitic可以带来以下好处:
- 出色的水平扩展能力
- 优秀的内置错误管理功能(重试、死信队列、错误传播等),具有高韧性
- 能够编写带计时器或信号的更复杂的业务流程
- 集中管理的工作流定义,并使用 Git 进行版本控制
- 在不停止运行中的工作流时更新工作流
- 内置的工作流状态监控
Infinitic 可以让你用熟悉的 Java 或 Kotlin 编程语言来定义和编排业务流程(更多详情请参阅文档)。你无需学习新的领域特定语言 (DSL) 来描述工作流,而是可以利用已用于与分布式微服务交互的代码,但执行将是事件驱动的。这种低摩擦的方式使得从头开始编写新的事件驱动工作流,或者将现有的同步控制器重构为健壮的异步工作流实现变得简单直接。
我们来看看一个订阅服务的简单月度账单流程为例说明。
流程始于用户订阅服务时。随后的每个月初,会启动一个循环检查是否用户仍然订阅服务。如果用户仍然订阅,将执行一系列操作:
1. 等下个月
2. 例如,获取消费记录 (ConsumptionService.get()
)
3. 请求支付(PaymentService::request
)
4., 创建发票 (InvoiceService::create
)
5. 通过电子邮件发送这张发票 (EmailService::send
)
邮件发送后,循环会再次检查用户是否仍然订阅。如果用户不再订阅,流程就会停止。
此工作流可以用 Kotlin 实现,如下所示:
正如你看到的,这段代码与你在业务流程管理中通常做的事情非常相似,只不过这段代码控制的是一个事件驱动的流程。
Infinitic 提供的 newService
函数接受一个服务接口作为输入,并返回该接口的模拟实现。如果对这个模拟实现的调用是一个新的请求,Infinitic 将触发一个事件来启动相应的服务执行。然而,如果该方法调用的结果已经被处理过,意味着结果已经存在,Infinitic 将直接从事件日志返回预先计算好的结果。
如果你想了解更多关于它是如何工作的细节,可以阅读事件驱动的“工作流即代码”引擎内部。
如何使用您的API构建事件驱动型服务Infinitic 提供即插即用的服务工作者,你只需要实现服务,就可以直接使用了:
- 定义用于业务流程的服务接口,可以使用 Java 或 Kotlin
- 通常,此代码会调用您的 API 的各种方法。确保在调用失败时抛出异常,以使 Infinitic 能够平滑地重试。
- 在 Infinitic 服务工作者 中采用此实现。
事件驱动的流程,使用带有 Service Workers 的功能调用现有的 API 驱动的微服务。
部署您的事件驱动程序要启动您新创建的事件驱动程序。
- 部署实现您业务流程的 工作流工作者,通过创建的服务接口来部署。
- 部署处理对您的 API 调用的 服务工作者。
- 设置一个 Apache Pulsar 实例。在进行这一步时,Infinitic 管理与 Pulsar 相关的所有方面,从主题拓扑、设置、模式管理到消费者和生产者实现。因此,您无需具备 Pulsar 的先前知识即可使用 Infinitic。如果您不想自己操作 Pulsar,可以使用 StreamNative、DataStax 或 CleverCloud 等公司提供的托管 Apache Pulsar 实例。
通过遵循这些步骤,您的业务流程将变得事件驱动,确保可靠且一致,同时继续使用现有的API服务。这种方法只需要很少的努力,只需要几周,而不是几个月的时间。
关于代码生成的一些额外想法这样一来,有了清晰的服务定义,例如通过像IDL这样的接口描述语言(例如用于REST API的OpenAPI或用于远程过程调用的gRPC),代码生成工具可以解析服务契约,并自动生成用于在Infinitic的Service Workers内部调用服务的样板代码。
这将使现有的API驱动微服务与Infinitic编排框架集成的过程更顺畅,减少人工干预并降低错误的可能性。我正在探索这一途径作为未来增强功能的一部分,旨在为采用Infinitic的开发者提供更好的使用体验。这种方法还可以帮助那些不希望使用Java或Kotlin的团队。
结尾利用 API 驱动的微服务建立可靠且一致的业务流程是一项具有挑战性的任务,但使用 Infinitic 的事件驱动协调方式可以显著减少可靠性和一致性的风险。
Infinitic 提供了一种强大的解决方案,通过利用您现有的 API 驱动的微服务,允许您开发基于事件驱动的业务流程。通过使用 Infinitic 的工作流实现方法,您可以构建天然具备弹性、可扩展性和可维护性的新业务流程。通常只需几周,而从零开始构建类似功能可能需要数月。
使用Infinitic进行事件驱动业务流程时,以下几点关键优势包括:
- 通过异步事件驱动的通信和优雅的服务故障恢复机制提高了可靠性。
- 即使在处理过程中出现故障,也能保持分布式系统中的数据一致性,确保数据完整。
- 使用Infinitic的工作流实施方法简化了复杂业务流程的开发和维护。
- 出色的水平扩展能力
- 内置错误管理功能
- 能够在不影响运行过程的情况下更新和版本管理工作流。
- 增强了运行工作流状态的可见性,方便监控和调试。
通过采用Infinitic,您可以未来保护关键业务流程,确保它们随着组织的成长保持可靠、一致和可扩展,而不受传统API驱动方法的限制所束缚。
有兴趣的话,可以看一下https://docs.infinitic.io 或者关注我的 substack https://infinitic.substack.com。
如果您需要咨询或专业支持服务,请随时联系我,可以通过 gilles@infinic.io。
共同学习,写下你的评论
评论加载中...
作者其他优质文章