休息服务之间的事务依赖

时间:2016-10-06 18:59:16

标签: web-services rest transactions

我们正在将我们的应用程序转换为支持SOA,主要是为了提供宁静的服务。我已经开发了服务,但是我现在担心如果服务2失败,如何回滚服务1的事务。

我有一个由三个服务组成的页面。如果任何服务失败,那么我必须将整个页面回滚到先前的状态,并确保从页面触发的所有异步服务调用也被回滚。

我没有任何指示如何处理这个问题。任何人都可以对此有所了解。

如果我没有意义并且必须提供更多信息,请告诉我

1 个答案:

答案 0 :(得分:0)

tl; dr :使用补偿操作和幂等性

更详细:

SOA和REST是架构风格。这也意味着,当从monolith迁移到SOA并从分布式事务迁移到REST以及从RPC(RMI等)迁移到REST时,您必须重新考虑事务。

让我们首先看看它在非REST世界中是如何工作的,然后看看它是如何变化的。您对当前应用程序的外观有点模糊,因此我将指出一系列场景。

整体式

当您拥有单一应用程序时,您的整个代码都驻留在同一个工件中,所有处理都在同一台机器上完成,并且所有数据访问都是集中的。您可以拥有一个涵盖所有内容的单个事务。您的DBMS授予您ACID属性。

分布式交易

有多种方法可以跨网络跨越事务,并使用2PC协调多个节点。这与monolith场景没有太大区别 - 除了延迟更多,回滚更多,扩展问题更多等等。

SOA

在SOA世界中,您停止使用数据库耦合服务,并使用服务接口来交换服务。这有很多好处,但也有一些后果,你应该知道。

在SOA中,您不使用分布式事务,但每个服务都有自己的数据库和自己的事务。当有两个服务和服务A调用服务B和B失败时,A可以识别此失败(捕获异常或让容器处理该异常)并回滚其自己的事务。但是,如果A成功调用B然后在提交自己的事务之前失败,那么就不可能在B处回滚事务,因为在B处事务已经提交。简而言之:您不再拥有SOA的ACID。原子性或一致性无法保证,只能部分隔离。习惯它。

事实上,ACID也是普通RDBMS的谎言。当它们按照纯ACID合规性运行时("可序列化")它们变得非常缓慢。因此,DBMS具有不同的isolation levels,您可以在其中进行某些快捷方式。实际上几乎没有人操作数据库,以至于他们确实保证了ACID。可能发生的不一致性非常罕见,因此您可以容忍它们。可能会发生不一致,您必须从中恢复或解决它们。

当你处理数据库之外的东西时,同样适用。您无法取消打印发票。你不能发送电子邮件等。你不能解开蛋糕。你必须找到合适的补偿行动。

这也是您在SOA环境中必须做的事情。可能会出现不一致,这意味着您必须自己处理它们。有几种方法可以这样做:

  • 如果它们非常稀有且数据不那么重要,您可以放心地忽略它们。
  • 如果它们非常稀有,您可以选择手动处理它们。如果每年有一位客户遇到问题,请在客户投诉,道歉并向他发送礼品时解决问题。
  • 如果这些问题的发生频率高于您可以手动处理的问题,请执行自动补偿操作。如果打印发票,请将其丢弃。如果您已发送,请发送取消。如果客户已经付款,请发送信用单等。

    您已经习惯在应用程序中执行补偿操作。您可以像错误的发票一样处理失败的服务。就像错误的发票示例一样,它在很大程度上取决于您可能想要处理的具体故障情况。也许正确的解决方案是删除一些数据库记录。或者您需要重复服务电话。或者您需要拨打另一个服务电话。我无法告诉你究竟需要做什么,但是当你想到它时你就会知道它。

REST

可能出错并且可能需要补偿操作的一件事是服务调用可能失败(由于多种原因)。在这种情况下,REST和HTTP有几种机制可以帮助您。

其中一种机制是idempotence。如果您的服务呼叫失败或者您不确定它是否成功,您只需重试服务呼叫即可。您需要使所有GET,PUT和DELETE操作具有幂等性,以便您的服务客户端可以安全地重试。 POST和PATCH操作不需要是幂等的,尽管特别是对于PATCH,如果它们仍然如此有用。

有相当复杂的机制(例如带有先决条件的呼叫)但实际上有了幂等性,你可以处理95%的问题。您习惯休息时可以阅读它们。一开始你应该坚持基础。如果你有充分的理由,只能使用更复杂的东西。

BTW:进行单元测试以检查幂等性是非常有帮助的。特别是如果你不习惯它或者有一些复杂的事情发生,建议你检查一下,因为你真的不想弄错。

结论

解决方案不是将事务引入SOA和REST,而是在开发应用程序时以面向服务和安静的方式进行思考。