如果REST上的事务无法实现,REST如何才能真正有用?

时间:2010-02-27 10:17:08

标签: web-services rest transactions standards

在研究REST时,可能任何人都会注意到的第一件事是没有定义任何事务语义,有人说这是隐含的反对什么是REST,而其他人说任何这样做的尝试都会导致“污染” REST系统。

但是,为了论证,REST确实成为了一种流行的'api'选择,并且宇宙中的每个网站都开始暴露出宁静的切入点。

如果没有交易行为,我们究竟如何才能使用(我说的是非补偿)?因为在我看来,REST的一个好处就是它打破了数据的组成部分,你会认为这会让智能客户端从多个服务组成数据(并添加和调整这些组合数据)。但是,如果我无法原子地和孤立地对这种数据组合进行更改,那么使用REST就变得毫无用处。

随着时间的推移和对严肃数据展示的需求的到来,我们想要的东西是:简单(REST在那里获胜),并支持事务行为,因此我们可以可靠地操作这些数据。

现在,我已经在我的研究中多次阅读了一个特定的论点,它与我们应该如何考虑REST中的事务有关,给出的例子是购物车,你隐含地在那里隔离因为购物车是你的。

但是我不同意这个论点,首先,购物车的隔离只是方便,这不是交易隔离......如果我同时对我的购物车进行操作,会发生什么呢?正在读取它的数据?我不希望我的应用程序的阅读部分看到“仍在交易中”的数据。

更不用说并非所有数据更改都具有隐式事务模型,而且多个服务上的事务肯定不会。

在我看来,事务需要发生,并且需要以一种方式发生,使实际的REST调用不知道事实(添加其余的有效负载是一个很大的不,但添加标题是正常的)

我已经阅读了一些关于如何通过REST创建事务模型的建议,并且编写的一些规范似乎是最新的。

有没有真正的想法?不应该存在比REST更多的东西,这样就可以利用REST的简单性来处理固态数据操作('酸'事务)。

如果不是,我们期望真的提高赌注,并告诉服务开发人员,如果他们想要在纯粹的数据世界中进行交互,他们需要支持像肥皂那样单一的东西吗?或者更糟糕的是尝试将自己的自定义事务支持构建到REST之类的东西中,使每个服务都不标准并破坏REST的全部功能?

提前感谢任何想法。


编辑,添加了简短的场景:

想象一个客户端表单处理相册的创建,为了方便该相册,而不是要求用户给艺术家资源的uri,他们可以从艺术家列表中选择(最有可能从艺术家目录)。

为了便于使用,客户可以手动编写艺术家姓名,这样他们就可以在发布方案中创建艺术家'内联'..客户端代码理解这一点,在发送创建专辑的请求之前,首先尝试确定艺术家是否已经存在,如果是,则获取该艺术家的uri,否则创建艺术家并获得艺术家uri。

客户端代码然后继续创建专辑,这是比平时更聪明的客户端,它不是坐​​在REST之上并且“愚蠢”发布,而是有一些处理纯粹REST逻辑的交互。

然而,在这种情况下,如果首先创建艺术家,保证不创建艺术家,除非是专辑,否则很高兴。

这不像交易所暗示的那样“关键”,但它定义了一组客户端代码更愿意作为一个操作发生的工作(毕竟,它使这看起来像是对一个操作的单个操作用户)。

我在这种情况下看到的唯一指导是让客户端在专辑创建失败时执行补偿操作,并特别要求删除艺术家。但这似乎有问题,因为客户假设艺术家是孤立的,尽管可能不太可能,如果另一个客户已经“看到”该艺术家并分配给它,会发生什么?

这些是关于进行数据更改的问题,虽然肯定存在其他差距(谁说艺术家不能在以后删除),但这些行为并不透明(即行动不是客户自动化的东西,但是用户特别要求的东西。)

我希望这有助于阐明这个话题。

10 个答案:

答案 0 :(得分:24)

我将假设当您谈论交易时,您正在讨论分布式Two Phase Commit协议。

如果我理解正确,您正试图了解如果REST无法支持跨不同REST请求的事务,我们将如何使用REST来执行跨多个系统的操作。问题是你正在做一个可能存在缺陷的假设,即我们应该使用事务来实现一致性。我们为使用它们付出的代价是什么,以及存在哪些替代品?

曾经在亚马逊工作并现在在微软工作的Pat Helland撰写了一篇论文Life beyond Distributed Transactions。在论文中,作者发表以下声明:

  

不幸的是,程序员正在努力   解决电子商务等业务目标,   供应链管理,财务,   和保健应用   越来越需要思考   没有分布的缩放   交易。他们这样做是因为   尝试使用分布式   交易太脆弱了   表现不佳。

他的论文探讨了可扩展和表现良好的分布式交易的替代解决方案。

也许REST会成功,因为它不支持交易。以下是Roy Fielding的一句话,他发明了术语REST

  

如果你发现自己需要一个   然后是分布式事务协议   你怎么可能说你的   架构基于REST?一世   根本无法看到你如何得到   一种情况(使用RESTful   客户端和应用程序状态   超媒体确定所有状态   过渡到下一个情况   需要分发协议   事务语义中的   客户端必须告诉服务器如何   管理自己的资源。

     

...现在我考虑“休息   交易“成为矛盾。

这是来自2009年6月9日的REST讨论列表中的消息。我无法提供链接,因为Yahoo组无用。

答案 1 :(得分:17)

如果您想在ReST应用程序中使用ReST API函数进行交易,通常是因为您仍然拥有您的技术人员服务人员谷歌。

让我们以另一种方式看待它。

肥皂谷歌: 打开交易,创建客户记录,创建订单记录,提交交易。

ReST谷歌: 询问服务器该做什么。服务器说“创建客户资源”,所以POST /客户。服务器说,“现在创建一个订单,如果你想”,客户通过跟随表单创建订单。

在ReST中,应用程序协议以创建和操作的资源表示,而不是根据具有事务边界的数据表示。

如果你想拥有一个跨越所有这些操作的长期运行的事务,那么决定启动它的是服务器,而不是客户端。

您仍然可以在服务器端实现长时间运行的事务。如果您尝试从客户端获取事务,那么您假设客户端已经知道它将执行的所有操作以及这些操作之间存在的事务边界。如果这是您对客户的期望,那么您已经放弃了休息架构的后期绑定,超媒体驱动的性质。

事实上,如果您没有使用ReST并且正在尝试使用RPC而不是http,那么您将遇到没有交易的问题。

答案 2 :(得分:14)

我认为通常需要交易的大多数操作都可以在没有它们的情况下进行重新设计。

例如,经典的银行转帐。假设我想将100美元从账户A转移到B:

Begin Transaction
  /Debit  A, $100  
  /Credit B, $100
Commit Transaction

这可以改写为:

 /Transfer  A, B, $100  

通过这种方式,服务器可以分两步执行此操作,但客户端的操作是一个逻辑意义上的单个原子操作。

我确信有很多例子可以更方便地进行全部或全部操作(而且我很好奇人们可以想出什么来解决它们),但我通常会在这里做一些事情。方式。

答案 3 :(得分:3)

REST操作可以启动事务,执行多个数据库或其他事务操作,然后提交或回滚 - 所有操作都在事务范围内。

REST不能做的不是事务的根。您无法启动事务,然后执行两个REST操作和数据库操作,然后将它们全部一起提交。这就像.NET中的ASMX Web服务的情况。它们可以是交易的根源,但仅此而已。他们成功多年,直到引入WCF,支持WS-Transactions。即使在今天使用WCF,大多数Web服务操作也不需要在您询问的意义上进行事务处理。

答案 4 :(得分:2)

这是一个有趣的话题。正如您所提到的,SOAP已经具备了这种功能,但是在SOAP成熟到人们考虑使用它进行真正的安全性和事务处理之前需要很多年。在那之前,它是CORBA。

SOAP的各种高级扩展,包括安全性和事务,为了让它们正确,许多人花了很多工作。这不会发生在一夜之间的REST,它可能永远不会发生。

我觉得REST目前流行的很多东西都是针对设计不当和过于复杂的SOAP实现的强烈反对,这是一种耻辱,因为SOAP不一定是那样的。与其他任何事情一样,它需要良好的设计才能使其正常工作。

答案 5 :(得分:2)

我认为使用REST的交易实际上是可以实现的。将事务视为可以创建(启动),编辑(发布更改)和删除(提交,回滚)的资源。发布到事务的更改不需要在提交事务之前修改全局状态,并且在提交期间,您可以强制执行您需要的任何全局状态一致性规则。当然,交易资源将通过授权规则得到保护。

您已经提到了这个概念的常见插图:

  

现在,我已经在我的研究中多次阅读了一个特定的论点,它与我们应该如何考虑REST中的事务有关,给出的例子是购物车,你隐含地在那里隔离因为购物车是你的。

     

但是我不同意这个论点,首先,购物车的隔离只是方便,这不是交易隔离......如果我同时对我的购物车进行操作,会发生什么呢?正在读取它的数据?我不希望我的应用程序的阅读部分看到“仍在交易中”的数据。

为什么不允许查看交易?只要您将其显示为实际状态,即待处理的更改列表,提供该功能实际上很有帮助。但如果您不希望它可见,您可以在资源上禁用GET

答案 6 :(得分:1)

看看OpenStreetMap API。我认为它是一种“REST”,它提供了一种“交易” - 在那里称为“变更集”。这就是你需要的吗?

答案 7 :(得分:1)

实际上,REST中的事务的工作方式与传统SOAP服务中应该工作的方式大致相同。

RPC样式的事务,客户端发出“begin transaction”命令(或某些隐式开始但不提交事务的操作),然后是一些额外的操作,然后是另一个隐式/显式“end transaction”命令,过时了。很久以前,Web Service世界就远离了RPC模型; SOAP中的RPC /编码甚至不符合WS-I!

而不是过程,今天的SOAP服务是围绕消息的概念构建的。单个消息包含执行完整事务所需信息的所有。如果您要提交订单,OrderRequest消息将包含客户信息,订单信息,订单详细信息,付款详细信息......服务器可能需要了解的有关单个订单的所有信息。

我们确实有WS-Transactions定义分布式事务的语义,但这些并不真正用于支持来自客户端的类似RPC的语义,它们用于在需要让多个服务参与时的编排交易。例如,您的订单服务需要登记支付处理服务以验证信用卡信息并发布付款,如果履行服务发现您缺货,或者类似的东西需要回滚...明白了。这一切都发生在服务器环境中,所以没有什么能阻止你在REST中做同样的事情。

在REST中,您有资源而不是消息,但这个概念非常相似。客户端提交(OrderRequestPUT资源而不是Order消息,而资源应包含完成事务所需的所有相同信息。不可否认,如果您尝试执行复杂的编排,您可能会发现REST与SOAP相比有点笨拙,但这并不意味着您不能继续使用REST作为前端,只是SOAP将更好地为您的后端服务提供服务。

但实际情况是,99%的人不需要WS-Transactions的复杂性。我知道这是因为我几乎只使用SOAP(WCF),很少使用WS-Transactions。

在REST中,“状态”驻留在客户端上。服务器告诉客户端,“这里是您创建此资源所需的所有信息(完成此事务)。”但是这个空白表单实际上并不是开始一个事务。由客户实际提供信息 - 填写表格,可以这么说。客户端在填写表单时所做的事情与服务器无关;当客户端最终将完成的表单发送到服务器时,它将完整地进行验证。它与工作单元类似,不同之处在于客户端是跟踪“工作”的人。

希望这可以更好地了解事务如何通过REST实现 。他们只依赖于更丰富的消息/资源概念和乐观并发形式。

答案 8 :(得分:1)

因为并非每个系统都需要交易。

答案 9 :(得分:0)

我知道非常成功的在线会计系统(SaaS),它具有基于REST的非事务性API,用于创建,检索和操作发票等。它们因其API和易于将其系统与其他方集成而广受好评。 。该API易于维护,可从各种平台使用,并确保向后兼容性相当简单。

缺乏交易可能是一个真正的痛苦,但大多数时候,当他们的服务器没有太多负载时,API工作得非常好。

有时,不完美就足够了。