当前位置:  开发笔记 > 编程语言 > 正文

REST中的事务?

如何解决《REST中的事务?》经验,为你挑选了7个好方法。

我想知道如何在REST中实现以下用例.甚至可以不牺牲概念模型吗?

在单个事务的范围内读取或更新多个资源.例如,将Bob的银行帐户中的100美元转入John的帐户.

据我所知,实现这一点的唯一方法是作弊.您可以POST到与John或Bob关联的资源,并使用单个事务执行整个操作.就我而言,这打破了REST体系结构,因为你实际上是通过POST隧道化RPC调用而不是真正操作单个资源.



1> Darrel Mille..:

考虑一个RESTful购物篮场景.购物篮在概念上是您的交易包装.以同样的方式,您可以将多个项目添加到购物篮,然后提交该篮子来处理订单,您可以将Bob的帐户条目添加到事务包装器,然后将Bill的帐户条目添加到包装器.当所有部分都到位后,您可以使用所有组件POST/PUT事务包装器.


为什么TransferMoneyTransaction不是一个可行的银行资源?
例如,如果在端点UpdateXYZ上执行HTTP DELETE会发生什么?它会删除XYZ吗?它是删除更新还是仅执行更新并忽略HTTP谓词删除.通过将动词保留在端点之外,可以消除混淆.
如果你确保你的端点引用名词那么标准的GET,PUT,POST,DELETE动词通常会直观地对那个名词做什么.RPC允许端点本身是动词,因此它们可能与HTTP动词冲突,并且意图变得混乱.
那么跨多个服务的交易呢?当你想要做一组"不相关"的变化时,服务公开没有隐式的事务容器,那么当我们转移到与你的实际数据完全无关的通用事务时,为什么会有一个特定的事务类型呢?变化.事务可能与restful不匹配,但似乎事务应该在ontop上分层,与其他调用无关,除了请求头将包含事务引用这一事实.
@meandmycode数据库事务应该在REST接口后面分层.或者,您可以将业务事务(而不是数据库事务)作为资源本身公开,然后在发生故障时需要采取补偿操作.
我得到了购物篮的例子,但是当你概括它时,它根本不是RESTful(你不是在运行资源).没有现实的银行相关资源来包装John和Bob.不错的答案!我觉得你肯定是朝着正确的方向前进.
我认为资源应该是现实生活中的对象,而不是服务(即方法调用).如果你能够组成模仿服务的资源,那么REST与RPC有何不同?
这不是我的意思..场景:我想在我的目录中添加一个专辑,在我的艺术家目录中添加一个艺术家(带有从专辑到艺术家的链接).我想要全部或全部,我不想补偿,操作应该感觉原子.
把你的场景作为一个单独的问题,我会在那里回答.评论是讨论这个的痛苦.此外,您也将获得其他人的意见.

2> Jon Watte..:

有一些重要案例没有通过这个问题得到解答,我认为这个问题太糟糕了,因为它在Google上的搜索条件排名很高:-)

具体来说,一个不错的属性是:如果你POST两次(因为一些缓存打中间),你不应该转移两次.

为此,您将事务创建为对象.这可能包含您已知的所有数据,并将事务置于挂起状态.

POST /transfer/txn
{"source":"john's account", "destination":"bob's account", "amount":10}

{"id":"/transfer/txn/12345", "state":"pending", "source":...}

完成此事务后,您可以提交它,例如:

PUT /transfer/txn/12345
{"id":"/transfer/txn/12345", "state":"committed", ...}

{"id":"/transfer/txn/12345", "state":"committed", ...}

请注意,此时多次放置并不重要; 即使是txn上的GET也会返回当前状态.具体来说,第二个PUT会检测到第一个PUT已经处于适当的状态,并且只是返回它 - 或者,如果你在它已经处于"已提交"状态后尝试将其置于"回滚"状态,你将得到一个错误,以及实际提交的事务.

只要您与单个数据库或具有集成事务监视器的数据库通信,此机制实际上就可以正常工作.您可能还会为交易引入超时,如果您愿意,甚至可以使用Expires标题表达.



3> 小智..:

在REST术语中,资源是可以使用CRUD(创建/读取/更新/删除)动词执行操作的名词.由于没有"转账"动词,我们需要定义一个可以用CRUD作用的"交易"资源.这是HTTP + POX中的一个示例.第一步是CREATE(HTTP POST方法)一个新的事务:

POST /transaction

这返回一个交易ID,例如"1234"并根据URL"/ transaction/1234".请注意,多次触发此POST不会创建具有多个ID的相同事务,也不会引入"挂起"状态.此外,POST不能始终是幂等的(REST要求),因此通常最好将POST中的数据最小化.

您可以将事务ID的生成留给客户端.在这种情况下,您将POST/transaction/1234创建事务"1234",如果服务器已存在则服务器将返回错误.在错误响应中,服务器可以返回具有适当URL的当前未使用的ID.使用GET方法向服务器查询新ID并不是一个好主意,因为GET永远不会改变服务器状态,创建/保留新ID会改变服务器状态.

接下来,我们使用所有数据UPDATE(PUT HTTP方法)事务,隐式提交它:

PUT /transaction/1234

  /account/john
  /account/bob
  100

如果ID为"1234"的事务之前已经是PUT,则服务器会给出错误响应,否则会显示OK响应和URL以查看已完成的事务.

注意:在/ account/john中,"john"应该是John唯一的帐号.


严重的错误?我知道PUT和POST之间存在差异,但是有一个松散的映射到CRUD."认真"?
将REST与CRUD等同是一个严重的错误.POST不一定意味着CREATE.
是的,认真的.CRUD是一种构建数据存储的方法; REST是一种构建应用程序数据流的方法.您可以在REST上执行CRUD,但不能在CRUD上执行REST.他们并不等同.

4> 13ren..:

很棒的问题,REST主要通过类似数据库的示例来解释,其中存储,更新,检索和删除了某些内容.很少有像这样的例子,服务器应该以某种方式处理数据.我不认为罗伊菲尔丁在他的论文中包含任何内容,毕竟这是基于http的.

但他确实将"代表性国家转移"称为国家机器,并将链接转移到下一个州.通过这种方式,文档(表示)跟踪客户端状态,而不是服务器必须这样做.通过这种方式,没有客户端状态,只有您所在的链接状态.

我一直在考虑这个,在我看来合理的是让服务器为你处理一些东西,当你上传时,服务器会自动创建相关的资源,并给你链接(事实上,它不会不需要自动创建它们:它只能告诉你链接,它只会在你跟随它们的时候创建它们 - 懒惰创建).并且还为您提供了创建相关资源的链接- 相关资源具有相同的URI但更长(添加后缀).例如:

    使用所有信息上载(POST)事务概念的表示. 这看起来就像一个RPC调用,但它确实创建了"建议的事务资源".例如:URI:/transaction 毛刺会导致创建多个这样的资源,每个资源都有不同的URI.

    服务器的响应表明创建的资源的URI,其表示 - 这包括用于创建新的"已提交事务资源"的相关资源的链接(URI).其他相关资源是删除建议交易的链接.这些是状态机中的状态,客户端可以遵循这些状态.从逻辑上讲,这些是在服务器上创建的资源的一部分,超出了客户端提供的信息.例如URI : /transaction/1234/proposed, /transaction/1234/committed

    POST到链接以创建"已提交的事务资源",该资源创建该资源,更改服务器的状态(两个帐户的余额)**.就其本质而言,此资源只能创建一次,并且无法更新.因此,不会发生提交许多事务的故障.

    您可以获取这两种资源,以查看其状态.假设POST可以更改其他资源,现在该提议将被标记为"已提交"(或者可能根本不可用).

这类似于网页的运作方式,最终的网页上写着"你确定要这么做吗?" 最终的网页本身就是交易状态的表示,其中包括转到下一个状态的链接.不只是金融交易; 也(例如)预览然后在维基百科上提交.我想REST中的区别在于状态序列中的每个阶段都有一个显式名称(它的URI).

在现实交易/销售中,交易的不同阶段(提案,采购订单,收据等)通常有不同的物理凭证.甚至更多的购房,结算等.

OTOH这对我来说就像玩语义一样; 将动词转换为名词使其成为RESTful的名词化让我感到不舒服,"因为它使用名词(URI)而不是动词(RPC调用)".即名词"已提交的交易资源"而不是动词"提交此交易".我想名义化的一个优点是你可以按名称引用资源,而不需要以其他方式指定它(例如维护会话状态,所以你知道"这个"事务是什么......)

但重要的问题是:这种方法有哪些好处?即这种REST风格以什么方式比RPC风格更好?对于网页而言,这项技术是否也有助于处理信息,而不是存储/检索/更新/删除?我认为REST的主要优点是可扩展性; 其中一个方面是不需要显式维护客户端状态(但是将其隐含在资源的URI中,并将下一个状态作为其表示中的链接).从这个意义上说它有所帮助 也许这有助于分层/流水线?OTOH只有一个用户会查看他们的特定交易,因此缓存它没有任何优势,所以其他人可以阅读它,http的大赢.



5> 小智..:

如果你回过头来总结一下这里的讨论,很明显REST不适用于许多API,特别是当客户端 - 服务器交互本质上是有状态的时,就像非平凡事务一样.为什么要跳过建议的所有箍,对于客户端和服务器,为了迂腐地遵循一些不适合问题的原则?更好的原则是为客户提供最简单,最自然,最有效的方式来组合应用程序.

总之,如果您真的在应用程序中执行了大量事务(类型,而不是实例),那么您实际上不应该创建RESTful API.


是的,但在分布式微服务架构的情况下应该有什么选择呢?

6> bbsimonbb..:

我离这个话题已经十年了.回来后,我无法相信当你谷歌休息+可靠时,你所涉及的宗教伪装成科学.混乱是神话.

我将这个广泛的问题分成三个:

下游服务.您开发的任何Web服务都将具有您使用的下游服务,其交易语法您别无选择,只能遵循.您应该尝试从服务的用户隐藏所有这些,并确保操作的所有部分作为一个组成功或失败,然后将此结果返回给您的用户.

您的服务.客户希望对Web服务调用有明确的结果,而直接在实质性资源上发出POST,PUT或DELETE请求的常见REST模式对我来说是一种糟糕且易于改进的提供这种确定性的方式.如果您关心可靠性,则需要确定操作请求.此id可以是在客户端上创建的guid,也可以是服务器上关系数据库的种子值,这无关紧要.对于服务器生成的ID,请求响应专用于交换id.如果此请求失败或一半成功,没问题,客户端只是重复请求.未使用的ID不会造成伤害.

这很重要,因为它允许所有后续请求完全是幂等的,因为如果它们重复n次,它们将返回相同的结果,并且不会再发生任何事情.服务器根据操作ID存储所有响应,如果它看到相同的请求,则重放相同的响应.这个模式的更全面的处理是在谷歌文档.该文档建议实现,我相信(!),广泛遵循REST原则.专家肯定会告诉我它是如何侵犯他人的.无论是否涉及下游交易,此模式都可用于对您的Web服务进行任何不安全的调用.

将您的服务集成到由上游服务控制的"事务"中.在网络服务的背景下,完整的ACID交易通常被认为是不值得的,但您可以通过在确认响应中提供取消和/或确认链接来极大地帮助您的服务的消费者,从而通过补偿实现交易.

您的要求是基本要求.不要让别人告诉你你的解决方案不是犹太人.根据他们解决问题的能力和简单程度来判断他们的架构.



7> TheSoftwareJ..:

您必须推出自己的"事务ID"类型的tx管理.所以这将是4个电话:

http://service/transaction (some sort of tx request)
http://service/bankaccount/bob (give tx id)
http://service/bankaccount/john (give tx id)
http://service/transaction (request to commit)

您必须处理在DB中(如果负载平衡)或在内存等中存储操作,然后处理提交,回滚,超时.

在公园里真的不是一个美好的一天.


我认为这不是一个特别好的例子.您只需要两个步骤:创建事务(在"挂起"状态下创建事务)和提交事务(如果未提交则提交,并将资源移动到已提交或回滚状态).
推荐阅读
携手相约幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有