如果无法实现基于REST的事务,那么REST到底有什么用呢?[关闭]


71

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

但为了争辩,可以说REST确实成为一种流行的“ api”选择,并且宇宙中的每个站点都开始公开宁静的入口点。

没有交易行为(我说的是非补偿性),这些功能到底有什么用?因为在我看来REST的好处之一是它分解了数据的组成部分,您可能会认为这使它们可以使智能客户端从多个服务中组成数据(并添加和调整组成的数据)。但是,如果我无法独立地原子地更改此数据组成,那么使用REST就变得毫无用处。

随着时间的流逝以及对严重数据公开的需求的到来,我们想要的是:简单(REST赢得了胜利),并支持事务行为,因此我们可以可靠地操作这些数据。

现在,我已经在研究中多次阅读了一个特定的论证,它与我们应该如何考虑REST中的事务有关,给出的示例是购物车,您在其中隐式具有隔离性,因为购物车是你的。

但是我不同意这种说法,首先,购物车具有隔离功能只是方便,这不是事务隔离。如果在应用程序的某些部分正在读取数据的同时对购物车进行操作,会发生什么情况从中?我不希望应用程序的读取部分看到“仍在事务中”的数据。

更不用说并非所有数据更改都具有隐式事务模型这一事实,而通过多种服务进行的事务肯定没有。

在我看来,事务需要发生,并且需要以一种使实际的REST调用不了解事实的方式发生(将剩余的负载添加为一个大的否定,但是添加标头可以)。

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

有什么真正的想法吗?不应有比REST更多的东西,以便可以利用REST的简单性来抵制可靠的数据操纵(“酸”交易)。

如果不是,我们是否有望真正做到这一点,并告诉服务开发人员,如果他们想在纯数据世界中进行交互,他们需要支持诸如肥皂之类的单片产品吗?甚至更糟糕的尝试将自己的自定义事务支持构建到REST之类的东西中,从而使每个服务都成为非标准服务并破坏REST的全部功能?

预先感谢您的任何想法。


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

想象一下一个客户窗体,该窗体负责创建专辑,为方便该专辑,而不是要求用户提供uri的艺术家资源,他们可以从艺术家列表中选择(很可能是从艺术家目录中获取) 。

为了便于使用,客户端可以手动输入歌手姓名,以便他们可以创建歌手“内联” ..在发布场景中,客户端代码理解这一点,并且在发送创建专辑请求之前,客户端首先尝试确定如果该艺术家已经存在,则为该艺术家获取uri,否则创建该艺术家并获取该艺术家uri。

然后,客户端代码继续创建相册,这比通常的客户端更聪明,它不仅仅位于REST和“笨拙”的发布之上,而是具有一些处理纯REST逻辑的交互。

但是,在这种情况下,最好先确保不创建艺术家,除非创建了专辑,除非首先创建了艺术家。

这并不像事务所暗示的那样“关键”,但是它定义了客户端代码宁愿作为一项操作发生的一组工作(毕竟,它使用户看起来像是一项操作)。

在这种情况下,我看到的唯一指导是在专辑创建失败的情况下让客户端进行补偿操作,特别是调用删除歌手。但这似乎是有问题的,因为委托人以为艺术家是被孤立的人,尽管可能性不大,如果另一个委托人已经“看到”该艺术家并分配给他,会发生什么?

这些是我对进行数据更改的关注,虽然当然还有其他差距(谁说不能再以后删除艺术家),但是这些动作并不透明(即,这些动作不是自动进行的)客户,但用户已明确要求的内容)。

我希望这有助于阐明该主题。


2
首先,您引用一些内容,但不提供链接。在建议这样冗长的论点时,我建议您这样做。其次,我投票决定关闭,因为这显然是有争议的,并且可能更适合博客。第三,我看不到问题。如果您出于某种目的想要进行交易,那么您是否只能实现它?还是您在侮辱“某人”?我不这么认为。我认为所有所谓的“ REST”实现都是不同的,恕我直言,这毫无意义。
丝绸之路

5
@约翰:同意。但是,与数十种“您最喜欢的编程笑话”样式的问题相比,该问题很有用且经过深思熟虑。
skaffman'2

5
感谢您的反馈,我将其更改为CW,至于结束问题,似乎有些倒退,如果这是一个麻烦的话题,那么人们应该争论自己的情况。创建主题,然后坐在“对自己很想”。
Meandmycode

10
@silky您指责原始海报具有争议性,然后以“ REST [是]毫无意义”结尾。
Darrel Miller 2010年

2
REST是否应该/可以支持事务是一个经常争论的话题,对于StackOverflow是一个非常有效的问题。我认为没有理由将其做成社区Wiki。
Darrel Miller 2010年

Answers:


25

我将假设当您谈论事务时,您正在谈论的是分布式两阶段提交协议。

如果我理解正确,那么您将尝试了解如果REST无法支持跨不同REST请求的事务,那么我们将如何使用REST执行跨越多个系统的操作。问题是您正在做出一个潜在的错误假设,即我们应该使用事务来实现一致性。我们为使用它们付出什么代价,存在哪些替代方案?

帕特·海兰德(Pat Helland)曾在亚马逊工作,现在就职于微软,他写了一篇论文《超越分布式事务的生活》。在本文中,作者发表以下声明:

不幸的是,努力解决诸如电子商务,供应链管理,财务和医疗保健应用程序之类的业务目标的程序员越来越需要考虑没有分布式事务的扩展。之所以这样做,是因为尝试使用分布式事务太脆弱且执行不佳。

他的论文探讨了可扩展且性能良好的分布式事务的替代解决方案。

REST可能会成功,因为它不支持事务。这是Roy Fielding的话,他发明了REST

如果您发现自己需要分布式事务协议,那么您怎么可能说您的架构基于REST?我简直看不到如何从一种情​​况(在客户端和超媒体上使用RESTful应用程序状态确定所有状态转换)到需要事务语义分布式协议的下一种情况,其中客户端必须告诉服务器如何管理自己的资源。

...目前,我认为“剩余交易”是一种矛盾。

这是2009年6月9日发布在REST讨论列表上的消息。由于Yahoo组没有用,我无法提供链接。


嗨,达雷尔,您好,感谢您的回复,我当然不会尝试推断自己关于REST应该如何工作的理论,这只是以“ OK”开始,所以我使用REST来完成这些方案。去做这个?' 并且出现了这些问题,事务可能不是我想要描述的确切语义,但是我希望我对原始问题所做的编辑能够更好地说明我的方案问题。感谢您的反馈。
Meandmycode

1
@meandmycode我认为您要描述的是工作流程。看看如何获得一杯咖啡:infoq.com/articles/webber-rest-workflow


17

如果您想在ReST应用程序中进行交易,则可以使用ReST API函数,这通常是因为您仍然需要Google的技术人员服务。

让我们换一种方式来看。

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

REST Google:请问服务器该怎么做。服务器说“创建客户资源”,所以POST / customers。服务器说,“如果需要,现在创建订单”,客户端按照表格创建订单。

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

如果您想拥有一个涵盖所有这些操作的长时间运行的事务,则服务器将决定启动它,而不是客户端。

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

因此,的确,如果您不执行ReST并尝试通过http进行RPC,您将遇到没有事务的问题。


27
Google的咯咯笑声导致它成为护目镜。
罗布

2
您的示例的问题在于,它完全是面向服务器的,客户端才是最重要的,在这个世界中,客户端希望将更改定向到域,并希望它们完全或不发生,而“您正在考虑错误”这一论点跌倒了。我确实得到了示例,但是我认为对于REST客户端的含义也许过于单纯,REST作为一种简单的数据更改通信方式,在我看来很重要。
meandmycode 2010年

8
如果您将REST术语重新定义为对您方便的术语,那么您将不会获得非常有帮助的答案。信不信由你,REST具有非常明确的含义,在这种情况下,REST客户端只能执行服务器认为可以通过超媒体执行的操作。与基于RPC的系统相比,在RESTful系统中,服务器对会话的控制方式更多。客户只需遵循提供给它的选项之一。
Darrel Miller 2010年

2
我并没有尝试重新定义REST,但是就真正的物理ui客户与它们的交互方式而言,我感觉更好,原因是为什么以这种受控方式进行的事务不是理想的,但实际上是一个工作单元有一些重要。
meandmycode

2
同样,在ReST中,服务器负责声明工作边界单元,而不是客户端。如果您希望客户知道这样的事情,而不是按照所在服务器导致它越过边界德,那么你最好还是把更多的知识,在客户端要比单纯的休息让。您将具有更强的耦合能力,而不会成为ReST,但是无论您要做什么,都可以做到。
SerialSeb 2010年

14

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

例如,经典的银行转帐。假设我要将$ 100从帐户A转移到B:

开始交易
  /借方A,$ 100  
  /信用B:$ 100
提交交易

可以将其重做为:

 /转让A,B,100美元  

这样,服务器可以分两个步骤执行此操作,但是来自客户端的操作是一个合乎逻辑的单个原子操作。

我敢肯定,有很多示例可以方便地进行全部或不执行任何操作(而且我很好奇人们可以提出什么解决方案),但是我通常以这种方式进行重做。


如果在服务器上完成传输但在将响应写到网络上之前,Internet连接中断,会发生什么情况?客户将认为转帐有误。在这种情况下,客户将再次尝试转移。
拉吉夫2013年

3
我建议在这种情况下使用乐观并发。例如,当您发送交易时,请包含一些值,以表明您所知道的数据状态。服务器在执行原子操作时可以检查此“最新更新”的值。如果匹配:继续。如果不是:错误。当客户端收到此并发错误时,它可以刷新所有内容并查看事务已发生。请注意,此问题不是REST独有的-常规RDBMS也有此问题。相关:en.wikipedia.org/wiki/Two_Generals'_Problem
Michael Haren

@Rajiv这显然是REST客户端问题,与服务无关...
inf3rno 2014年

3
这不是RPC,而不是REST吗?
jhegedus '16

1
是的,这有点道理,所以想法是尝试尽可能多地执行CRUD / REST,因此REST实际含义的一部分基本上就是使API尽可能简单,即CRUD +事务限于单个实体/行(使用乐观的“锁定”)。Transfer在这个例子中,OTH可以看作是一个事件。这与事件源的想法产生了很好的共鸣。
jhegedus

3

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

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


1
我认为大多数人都理解,在其余部分正在起作用的“操作”中,从某种意义上说,对实体的更改应该看起来是原子的,并且不应使数据处于损坏状态。这似乎有些明显,也许甚至超出了REST的范围,我希望单个操作成功与否。我的问题特别是关于在运营之间进行交易以及人们对A)关于此操作的想法,B)试图实现他们所看到的这种情况的反馈。
Meandmycode

2

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

SOAP的各种高级扩展,包括安全性和事务,为使它们正确无误,需要很多人进行大量工作。REST不会在一夜之间发生这种情况,也可能根本不会发生这种情况。

我觉得REST当前流行的大部分原因是对设计欠佳和过于复杂的SOAP实现的一种反弹,这是一种遗憾,因为SOAP不必那样。与其他任何东西一样,它需要良好的设计才能使其正常工作。


我个人不介意肥皂,我认为这种交换完全是针对机器的,因此这些消息是否“冗长”到什么程度并没有真正打扰我,而且我认为作为一种体系结构,它可以很好地工作。但是,它确实提高了客户端必须具备的复杂程度的标准,这正是REST的来龙去脉,当然,针对REST进行全面考虑的事务处理模型增加了这一标准,但是我认为没有什么比SOAP更好的了。
Meandmycode

2

因为并非每个系统都需要事务。


在需要交易的系统中,大多数将不需要分布式交易。
约翰·桑德斯

谁说的?如果您正在编写开放式api,您如何知道谁将使用您的服务?关于该主题的描述可能不是最好的,我敢肯定REST总是会占有一席之地,但是当涉及到并非专门用于“交易”的服务的组合时,REST似乎就不可能了。是吗 是啊,那是个限制,现在去写一个像个好男孩一样的肥皂服务,或者实际上是否有一些工作可以尝试在REST上分层一些交易行为?许多标头可以更改REST请求的结果,那么为什么不(即)事务标头呢?
meandmycode 2010年

@meandmycode:只是数人。如果房间里的人头不多,这不是我的错。分布式事务中需要多少个SOAP Web服务?我还没有看到我的第一个。
约翰·桑德斯

@John,我一开始不确定您的意思,但是就交易而言,我在最初的帖子中写了一个场景(很常见),我指出了有关没有交易如何操作集必须如何处理的要点。手动处理回滚,以及这些操作仍然存在缺陷。可以选择说,那些事情不会打扰我,这是一回事,但是有些系统具有这样的“不统一”端是有问题的,并且与“损坏”数据相比,事务的性能开销是绝对可以接受的。
meandmycode

@meandmycode:我们似乎在争论的是我的建议,即需要分布式事务的系统集是需要事务的系统集的子集。
约翰·桑德斯

1

看一下OpenStreetMap API。我认为它是一种“ REST”,它提供了一种“事务” –在那里称为“变更集”。那是你需要的吗?


不是“休息的种类”。不安 URI已记录,文档之间未使用任何链接。它比说Twitter或Flickr更好,但是它远不是一个超媒体应用程序,因此它不会令人不安。
SerialSeb 2010年

这很有趣,它是我以前见过的REST的示例之一,但是此imo污染了其余模型,链接变为事务感知,这导致链接和资源变为事务感知,这绝对不是我认为事务性REST应该走的路线。
meandmycode 2010年

我们已经看到,事务对于客户端了解并没有什么用处,并且由于ReST与客户端-服务器交互有关,因此不存在事务性ReST。我不确定我是否理解您对链接了解交易的评论?客户端使用链接来对整个应用程序进行状态更改。如果交易边界或UoW边界被链接后面的客户穿越,则在没有客户知识的情况下完成交易。
SerialSeb 2010年

@serialseb:为什么您将自己局限于无法理解交易的客户?事务有什么特别之处,以至于您无法想象客户平台会理解它们?
约翰·桑德斯

因为HTTP是ReST中的应用程序协议,并且HTTP不制定事务。实现供客户端使用的显式事务支持(而不是状态转换所固有的事务边界),这意味着您要重新引入以前不存在的耦合。关于ReST和交易的文献很多,在此不再赘述。
SerialSeb 2012年

1

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

RPC样式的事务已过时,在该事务中,客户端发出“开始事务”命令(或隐式开始但未提交事务的某些操作),然后执行一些其他操作,再执行另一个隐式/显式的“结束事务”命令。很久以前,Web服务世界已经脱离了RPC模型。RPC / SOAP编码甚至不符合WS-I!

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

我们确实有WS-Transactions,它们为分布式事务定义了语义,但是它们并不是真正旨在支持来自客户端的类似RPC的语义,当您需要让多个服务参与同一事务时,它们是为业务流程而设计的。例如,您的订单服务需要注册一个付款处理服务以验证信用卡信息并过帐付款,如果履行服务发现您缺货或类似的东西,则需要将其回滚...您明白了。这一切都是在服务器环境中进行的,因此实际上没有什么可以阻止您在REST中执行相同的操作。

在REST中,您拥有资源而不是消息,但是概念实际上非常相似。OrderRequest客户提交PUT一条Order资源而不是一条消息,该资源应包含完成交易所需的所有相同信息。诚然,如果您要执行复杂的业务流程,则与SOAP相比,REST可能会显得有些笨拙,但这并不意味着您不能继续将REST用于前端,只是SOAP将为您提供更好的服务您的后端服务。

但是,现实是,人们有99%的时间不需要WS-Transactions的复杂性。我知道这一点是因为我几乎只使用SOAP(WCF),很少使用WS-Transactions。

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

希望这给的交易如何才能成为一个更好的主意,通过REST实现。他们只是依靠更丰富的消息/资源概念和乐观并发形式。


@Aaronaught:他谈论的是分布式事务,其中几个数据库操作,Web服务调用或其他事务操作都使用三相提交全部组合为一个事务。
约翰·桑德斯

@约翰·桑德斯:那不是我的样子。他似乎在谈论允许客户设置事务边界,以便将顺序的Web服务调用包装在原子事务中。我的答案是解释为什么在REST体系结构甚至现代SOAP体系结构中这毫无意义。我什至提到分布式交易,为什么我不认为它们适用于这个问题。
Aaronaught

@Aaronaught:在他的第三段中,他谈到了客户能够从多个来源组合数据。另外,请考虑通常,多个Web服务调用不必在同一服务器上或使用同一服务,并且通常可以与其他事务操作组成。但不是使用REST。
约翰·桑德斯

@约翰·桑德斯(John Saunders):但是请阅读他的示例,他在其中谈论有关添加艺术家和专辑的问题。不必是分布式事务。无论如何,我从未听说过尝试使用REST在多个服务中组成一个资源。这似乎与REST的概念背道而驰。
Aaronaught

@Aaronaught:一般的问题是-如果您拥有一组SOAP服务,数据库事务等,是否可以将SOAP服务之一替换为REST服务?答案是不”。然后问题变成:“这会使REST失效吗?”
约翰·桑德斯

1

我认为使用REST的交易实际上是可以实现的。将事务视为一种资源,您可以创建(开始),编辑(通过更改发布)和删除(提交,回滚)。在提交事务之前,发布到事务的更改无需修改全局状态,并且在提交过程中,您可以实施所需的任何全局状态一致性规则。当然,交易资源将通过授权规则进行保护。

您已经提到了此概念的常见示例:

现在,我已经在研究中多次阅读了一个特定的论证,它与我们应该如何考虑REST中的事务有关,给出的示例是购物车,您在其中隐式具有隔离性,因为购物车是你的。

但是我不同意这种说法,首先,购物车具有隔离功能只是方便,这不是事务隔离。如果在应用程序的某些部分正在读取数据的同时对购物车进行操作,会发生什么情况从中?我不希望应用程序的读取部分看到“仍在事务中”的数据。

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


@Jacob:除非交易的所有部分都由同一服务执行,否则此操作无效。如果第1部分是服务1,第2部分是服务2,第3部分又是服务1,第4部分在本地数据库中怎么办?您的技术无法解决该问题。
约翰·桑德斯

2
当然可以。协作服务仅需要传达URL,而协作服务器则需要设置用于授权访问事务的规则。
雅各布

2
@ inf3rno:对不起,但您误会了。看一下WS-ReliableMessaging,它考虑了网络故障。
约翰·桑德斯

2
@ inf3rno:我想您没有阅读我链接到的Wikipedia文章。使用非SOAP解决方案(例如HP的Reliable Transaction Router)已经进行了十多年的分类。我是哪个产品的开发人员,所以请别告诉我这是做不到的。这是已经在银行,证券交易所和铁路部门运行的软件,因此您似乎不同意现实。
约翰·桑德斯

1
很难接受:-P也许我只是不了解这些解决方案背后的算法,您能告诉我更多关于它们的信息吗?(链接就足够了)
inf3rno 2014年

0

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

缺少事务可能是真正的难题,但是在大多数情况下,当服务器的负载不太高时,API会很好地工作。

有时候,低于完美就足够了。


我喜欢关于简单性的争论,但是我认为从更大的角度来看如何使用REST,这将要求客户非常有纪律,并且几乎要保证他们的操作能够正常工作(重大灾难性故障,例如服务器宕机)。
meandmycode 2010年

您为什么不给服务命名?我们一直在寻找优秀的REST API作为示例。
Darrel Miller 2010年

@达雷尔·米勒(Darrel Miller):e-conomic.com
符文(Rune)

我找不到任何REST api信息。我可以使用使用SOAP与服务器对话的客户端库来联系的唯一api文档。我错过了什么?
Darrel Miller'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.