《微服务》一书。 开发和重构模式»

图片 嗨,habrozhiteli! 如果很长时间以来,您看来公司中所有开发和部署的速度都减慢了,那就去微服务架构。 它提供了各种复杂性的应用程序的连续开发,交付和部署。

该书面向大型公司的开发人员和架构师,讲述了如何按照微服务架构的精神设计和编写应用程序。 它还描述了如何重构大型应用程序-整体变成了一组微服务。

我们为您提供了熟悉“微服务架构中的事务管理”这一段落的信息。

工业应用程序处理的几乎所有请求都作为数据库事务的一部分执行。 此类应用程序的开发人员使用简化了事务处理的框架和库。 一些工具提供了用于手动启动,提交和回滚事务的命令性API。 而且像Spring这样的框架具有声明机制。 Spring支持@Transactional批注,该批注会自动调用事务中的方法。 因此,编写事务性业务逻辑变得非常简单。

更准确地说,在访问单个数据库的整体应用程序中,管理事务很简单。 如果应用程序使用多个数据库和消息代理,此过程将变得更加困难。 嗯,在微服务架构中,事务涵盖了多个服务,每个服务都有自己的数据库。 在这种情况下,应用程序应使用更复杂的事务处理机制。 您将很快看到,在现代应用程序中,传统的分布式事务处理方法不可行。 基于微服务的系统应该使用讲故事的方法。

但是在继续叙述之前,让我们看看为什么事务管理在微服务架构中创建了如此众多的复杂性。

4.1.1。 微服务架构和对分布式事务的需求


假设您是FTGO的开发人员,并且负责实施createOrder()系统操作。 如第2章所述,此操作必须确保客户可以下订单,检查订单详细信息,授权客户的银行卡并在数据库中创建订单记录。 这些动作的实现在整体应用程序中将相对简单。 验证订单所需的所有数据已准备就绪且可用。 另外,ACID事务可用于确保数据一致性。 您只需为createOrder()服务方法指定@Transactional批注。

但是,在微服务架构中执行此操作要困难得多。 如图所示。 4.1,createOrder()操作所需的数据分散在多个服务中。 createOrder()从Consumer服务读取信息,并更新Order,Kitchen和Accounting服务的内容。

由于每个服务都有自己的数据库,因此应使用一种机制来协调它们之间的数据。

4.1.2。 分布式交易问题


确保多个服务,数据库或消息代理之间的数据一致性的传统方法是使用分布式事务。 分布式事务管理的事实上的标准是X / Open XA(请参阅en.wikipedia.org/wiki/XA )。 XA模型使用两阶段提交(2PC)以确保保存或回滚对事务的所有更改。 这要求数据库,消息代理,数据库驱动程序和消息传递API符合XA标准,并且还需要一种用于分发全局XA事务标识符的进程间通信机制。 大多数关系数据库和某些消息代理都是XA兼容的。 例如,基于Java EE的应用程序可以使用JTA执行分布式事务。

图片

尽管它们很简单,但是分布式事务仍然存在许多问题。 许多现代技术(包括MongoDB和Cassandra等NoSQL数据库)都不支持它们。 某些现代消息代理(例如RabbitMQ和Apache Kafka)不支持分布式事务。 因此,如果您决定使用分布式事务,则许多现代工具将不可用。

分布式事务的另一个问题是它们是同步IPC的一种形式,这会损害可用性。 为了提交分布式事务,其中涉及的所有服务都必须可访问。 如第3章所述,系统可访问性是所有交易参与者可访问性的产物。 如果两个具有99.5%可用性的服务参与分布式事务,则总体可用性将为99%,这要少得多。 每一项附加服务都会降低可用性。 Eric Brewer制定了CAP定理,该定理指出系统只能具有以下三个属性中的两个:一致性,可访问性和分区抵抗性(en.wikipedia.org/wiki/CAP_定理)。 如今,架构师青睐负担得起的系统,从而牺牲了一致性。

乍一看,分布式交易似乎很有吸引力。 从开发人员的角度来看,他们具有与本地交易相同的软件模型。 但是由于前面描述的问题,该技术在现代应用中不可行。 第3章介绍了如何在不使用分布式事务的情况下将消息作为数据库事务的一部分发送。 为了解决确保微服务体系结构中的数据一致性的更复杂的问题,应用程序必须基于松耦合异步服务的概念使用不同的机制。 而这里的叙述派上用场了。

4.1.3。 使用讲故事模板来保持数据一致性


讲故事是一种在不使用分布式事务的情况下确保微服务体系结构中数据一致性的机制。 为需要更新几个服务中的数据的每个系统团队创建了叙述。 这是一系列本地事务,每个事务都使用前面提到的ACID事务的熟悉的框架和库来更新一项服务中的数据。

讲故事模板

使用一系列使用异步消息进行协调的本地事务来确保服务之间的数据一致性。 请参阅microservices.io/patterns/data/saga.html

系统操作将启动叙述的第一阶段。 一项本地交易的完成导致以下结果。 在第4.2节中,您将看到如何使用异步消息来完成这些步骤的协调。 异步消息传递的一个重要优点是,即使无法访问一个或多个参与者,它也可以确保叙述的所有阶段都已完成。

叙述与ACID交易有几个重要区别。 首先,它们缺乏隔离性(有关此内容的更多信息,请参见第4.3节)。 另外,由于每个本地事务都会捕获其更改,因此要回滚该故事,您必须使用补偿事务,我们将在本节稍后讨论。 考虑一个讲故事的例子。

叙述示例:创建订单


在本章中,我们以“创建订单”叙述为例(图4.2)。 它实现了createOrder()操作。 第一个本地交易由外部订单创建请求触发。 其余五笔交易是一个接一个地触发的。

图片

该叙述包括以下本地事务。

1.订购服务。 创建状态为APPROVAL_PENDING的订单。

2.服务消费者。 检查客户是否可以下订单。

3.厨房服务。 检查订单的详细信息,并创建状态为CREATE_PENDING的请求。

4.会计服务。 授权客户的银行卡。

5.厨房服务。 将应用程序的状态更改为AWAITING_ACCEPTANCE。

6.服务订单。 将订单状态更改为“已批准”。

在第4.2节中,我将展示故事中涉及的服务如何使用异步消息相互交互。 该服务在本地事务完成时发布一条消息。 这启动了叙事的下一个阶段,不仅使参与者的凝聚力减弱,而且保证了叙事的充分实施。 即使收件人暂时不可用,代理也将缓冲消息,直到可以传递为止。

叙述似乎很简单,但是它们的使用会带来一些困难,尤其是它们之间缺乏隔离。 该问题的解决方案在第4.3节中描述。 另一个不重要的方面是发生错误时回滚更改。 让我们看看这是如何完成的。

叙述使用抵消交易回滚更改


传统的ACID事务具有一个重要功能:如果检测到违反业务规则,则业务逻辑可以轻松回滚事务。 它仅执行ROLLBACK命令,数据库将取消到目前为止所做的所有更改。 不幸的是,故事无法自动回滚,因为故事在每个阶段都会捕获本地数据库中的更改。 例如,这意味着如果在创建订单说明的第四阶段中银行卡授权失败,则FTGO应用程序必须手动取消在前三个阶段中所做的更改。 您必须编写所谓的抵消交易。

假设故事中的第(n + 1)次交易失败。 有必要抵消之前n次交易的后果。 从概念上讲,这些Ti阶段中的每个阶段都有自己的补偿交易Ci,抵消了Ti的影响。 为了补偿前n个阶段的影响,叙述必须以相反的顺序执行每个事务Ci。 序列如下所示:T1 ... Tn,Cn ... C1(图4.3)。 在此示例中,步骤Tn + 1失败,这需要取消步骤T1 ... Tn。

图片

叙述以与原始顺序相反的顺序执行补偿性交易:Cn ... C1。 在此,与Ti相同的顺序执行机制起作用。 Ci的终止应启动Ci-1。

以创建订单的叙述为例。 它可能由于多种原因而失败。

1.有关客户的信息不正确,否则不允许客户创建订单。

2.有关餐厅的信息不正确,或餐厅无法接受订单。

3.无法授权客户的银行卡。

如果本地交易失败,则叙事协调机制必须执行补偿性步骤,以拒绝该订单,甚至可能拒绝该订单。 在桌子上。 4.1在创建订单叙述的每个阶段收集补偿性交易。 应该注意的是,并非每个阶段都需要补偿交易。 例如,这适用于读取操作(例如verifyConsumerDetails()或authorizeCreditCard()操作),之后的所有步骤总是成功的。

图片

在第4.3节中,您会发现“创建订单”叙述的前三个阶段称为可用于补偿的交易,因为它们后面的步骤可能会失败。 第四步称为转账交易,因为后续步骤永远不会失败。 最后两个步骤称为可重复事务,因为它们总是成功结束。

要了解如何使用补偿性交易,请设想一下客户的银行卡授权失败的情况。 在这种情况下,该叙述执行以下本地事务。

1.订购服务。 创建状态为APPROVAL_PENDING的订单。

2.服务消费者。 检查客户是否可以下订单。

3.厨房服务。 检查订单的详细信息,并创建状态为CREATE_PENDING的请求。

4.会计服务。 尝试授权客户的银行卡失败。

5.厨房服务。 将应用程序的状态更改为CREATE_REJECTED。

6.服务订单。 将订单状态更改为拒绝。

第五和第六阶段是补偿交易,这些交易取消了Kitchen服务所做的更新,并因此取消了Order。 协调叙事逻辑负责直接交易和抵消交易的顺序。 让我们看看它是如何工作的。

关于作者


Chris Richardson是POJO in Action(Manning,2006年)的开发人员,架构师和作者,该手册描述了如何使用Spring和Hibernate框架构建企业级Java应用程序。 他拥有Java冠军和JavaOne摇滚之星的荣誉头衔。

克里斯开发了CloudFoundry.com的原始版本,这是Amazon EC2的Java PaaS平台的早期实现。

现在,他被认为是微服务领域公认的意识形态领导者,并定期在国际会议上发表演讲。 克里斯创建了microservices.io,其中包含微服务设计模式。 他还为正在转向微服务架构的组织在全球范围内进行了咨询和培训。 克里斯目前正在他的第三家创业公司Eventuate.io上工作。 它是用于开发事务微服务的软件平台。

»这本书的更多信息可以在出版商的网站上找到
» 目录
» 摘录

小贩优惠券可享受25%的折扣-微服务模式
支付纸质版本的书后,就会通过电子邮件发送电子书。

Source: https://habr.com/ru/post/zh-CN462519/


All Articles