如果通过REST进行交易是不可实现的,那么REST如何才能真正有用?
在研究REST的时候,可能有人会注意到的第一件事情是没有定义任何事务语义,有人说这是隐含地反对REST的,而另一些人则认为任何尝试这样做都会导致REST系统。
但是为了争辩起见,REST确实成为了stream行的“api”select,宇宙中的每个站点都开始暴露出平静的入口点。
如果没有交易行为,这些可用性究竟如何(我说的是无补偿的)? 因为在我看来,REST的好处之一就是它打破了数据的组成部分,这样你就可以打开它让智能客户端从多个服务组成数据(并添加和调整这些组合的数据)。 但是,如果我不能自己对这个数据组合进行更改,那么使用REST就变得毫无用处。
随着时间的推移以及对严肃的数据展示的需求的到来,我们需要的东西是:Simple(REST在那里获胜),并且支持事务行为,所以我们可以可靠地处理这些数据。
现在,我已经在我的研究中多次阅读了一个特定的论证,并且涉及到我们应该如何考虑REST中的事务,并且给出的示例是购物车,因为购物车隐含地具有隔离,因为购物车是你的。
然而,我不同意这个观点,首先,购物车的隔离仅仅是方便的,这不是一个交易隔离。如果我同时对我的购物车进行操作,而我的应用程序的某些部分正在读取数据从中? 我不希望我的应用程序的阅读部分看到“仍在交易中”的数据。
更不用说,并非所有的数据变化都有一个隐含的事务模型,多个服务上的事务处理肯定不会。
在我看来,事务需要发生,并且需要以使得实际的REST调用不知道事实的方式发生(添加到其余的有效负载是一个很大的否定,但添加标头是可以的)。
我已经阅读了一些关于如何通过REST创build事务模型的build议,并且一些正在编写的规范似乎是最近的。
有没有关于这个的真实想法? 不应该有比REST更多的东西,这样REST的简单性就可以用来抵御可靠的数据操作(“酸”交易)。
如果没有,我们是否真的想要赌注,并告诉服务开发者,如果他们想要在纯数据世界中进行交互,他们需要支持像肥皂这样可以说是单一的东西? 或者更糟的是尝试将自己的自定义事务支持构build到REST之类的东西中,使得每个服务都是非标准的并打破了REST的全部function?
在此先感谢您的任何想法。
编辑,添加简短的情况:
设想一个处理相册创build的客户表单,为了方便使用该相册,而不是要求用户给出艺术家资源的URI,他们可以从艺术家列表中select(最有可能从艺术家目录中获取) 。
为了便于使用,客户可以手动编写艺术家姓名,以便他们可以在发布场景中创build艺术家“内嵌”..客户端代码理解这一点,并且在发送请求创build相册之前,首先尝试确定如果艺术家已经存在,如果是的话,获得该艺术家的uri,否则创build艺术家,并获得艺术家uri。
然后,客户端代码继续创build相册,这是比平常更聪明的客户端,它不是坐在REST之上,“愚蠢”的发布,而是有一些交互处理纯粹的REST逻辑。
然而,在这种情况下,如果艺术家是首先创build的,那么保证艺术家不会被创build,除非专辑是创build的。
这不像交易所暗示的那样“关键”,但是它定义了客户端代码倾向于作为一个操作发生的一组工作(毕竟,它使得这看起来像对用户的单个操作)。
我在这个场景中看到的唯一指导就是让客户端在相册创build失败的情况下进行补偿操作,特别是打电话删除艺术家。 但这似乎有问题,因为客户假设艺术家是孤立的,尽可能不太可能,如果另一个客户已经“看到”该艺术家,并分配给它会发生什么?
这些是我对数据变化的担忧,虽然还有其他的差距(谁说艺术家不能在晚些时候被删除),那么这些行为是不透明的(即,行为不是自动的客户端,但用户特别要求的东西)。
我希望有助于阐明这个话题。
我将假定当你谈论事务时,你正在谈论一个分布式的两阶段提交协议。
如果我理解正确,那么您正试图了解如果REST无法支持跨不同REST请求的事务,我们将如何使用REST执行跨多个系统的操作。 问题是你正在做一个有潜在缺陷的假设,我们应该使用事务来实现一致性。 我们付出什么代价来使用它们,还有哪些替代scheme?
曾经为亚马逊工作,现在在微软工作的帕特·赫兰德(Pat Helland)写了一篇论文“分布式事务以外的生活” 作者在文章中做出如下声明:
不幸的是,努力解决电子商务,供应链pipe理,财务和医疗保健应用程序等业务目标的程序员越来越需要思考如何在没有分布式事务的情况下进行扩展。 他们这样做是因为使用分布式交易的尝试太脆弱,performance不佳。
他的论文探讨了分布式事务的替代解决scheme,这些解决scheme的规模和性能都不错
也许REST会成功,因为它不支持事务。 这里是Roy Fielding的一句名言,他发明了REST这个词
如果您发现自己需要分布式事务协议,那么您怎么可能说您的架构基于REST? 我只是看不到如何从一种情况(使用客户端上的RESTful应用程序状态和超媒体来确定所有状态转换)得到需要分布式事务语义协议的情况,其中客户端必须告诉服务器如何pipe理自己的资源。
…现在我认为“rest交易”是一个矛盾。
这是来自2009年6月9日REST讨论列表上的一条消息。由于雅虎组是无用的,我无法提供链接。
如果您想在ReST应用程序中进行交易,那么在ReST API函数中,通常是因为您仍然拥有技术人员的webservice人员。
我们来看另一种方式。
肥皂Google上:打开一个交易,创build一个客户logging,创build一个订单logging,提交交易。
重新安装Google:询问服务器要做什么。 服务器说“创build客户资源”,所以POST /客户。 服务器说,“现在如果你想要创build一个命令”,客户端按照下面的格式创build命令。
在ReST中, 应用程序协议是用创build和操作的资源来表示的,而不是用具有事务边界的数据来表示的。
如果你想有一个跨越所有这些操作的长时间运行的事务,那就是决定启动它的服务器 ,而不是客户端。
您仍然可以在服务器端实现长时间运行的事务。 如果你试图从客户端获得事务,那么你认为客户端已经知道它将要执行的所有操作以及这些操作之间存在的事务边界。 如果这就是您对客户的期望,那么您已经放弃了后期绑定,rest架构的超媒体驱动本质。
所以的确,如果你没有使用ReST,并试图通过http来适应RPC,那么你将会遇到没有事务的问题。
我认为大多数通常需要交易的行为都可以在没有他们的情况下进行修改。
例如,经典银行转账。 假设我想从账户A向B移动100美元:
开始交易 /借记卡A,$ 100 /学分B,$ 100 提交交易
这可以改写为:
/转移A,B,$ 100
通过这种方式,服务器可以分两步完成,但是客户端的操作是一个单一的,逻辑上合理的primefaces操作。
我敢肯定,有很多例子可以更方便的做一些全部或者没有的操作(我很好奇人们可以想出什么来解决它们),但是我通常以这种方式来重做。
REST操作可以启动事务,执行多个数据库或其他事务操作,然后提交或回滚 – 全部在事务范围内。
REST不能做的事情不是事务的根源。 你不能启动一个事务,然后执行两个REST操作和一个数据库操作,然后一起提交它们。 这就像.NET中ASMX web服务的情况一样。 他们可以成为交易的根源,但就是这样。 他们成功了多年,直到WCF被引入,支持WS-Transactions。 即使在今天,使用WCF,大多数Web服务操作也不需要事务性的问题。
我认为使用REST的事务实际上是可以实现的。 将事务视为可以创build(启动),编辑(发布更改)和删除(提交,回滚)的资源。 发布到事务中的更改不需要在事务提交之前修改全局状态,并且在提交期间,可以强制执行任何需要的全局状态一致性规则。 交易资源当然会通过授权规则来保护。
你已经提到了这个概念的常见例子:
现在,我已经在我的研究中多次阅读了一个具体的论证,并且涉及到我们应该如何考虑REST中的事务,并且给出的示例是购物车,因为购物车隐含地具有隔离性,因为购物车是你的。
然而,我不同意这个观点,首先,购物车的隔离仅仅是方便的,这不是一个交易隔离。如果我同时对我的购物车进行操作,而我的应用程序的某些部分正在读取数据从中? 我不希望我的应用程序的阅读部分看到“仍在交易中”的数据。
为什么你不允许查看交易? 只要您按原样显示待处理更改的列表,提供该function实际上很有帮助。 但是,如果你不希望它是可见的,你可以禁用资源上的GET
。
看看OpenStreetMap API 。 我认为这是一种“rest”,它提供了一种“交易” – 在那里被称为“变更集”。 那是你需要的吗?
这是一个有趣的话题。 正如你所提到的,SOAP已经具备了这种function,但是在SOAP成熟之前需要很多年的时间,人们才会考虑进行真正的安全性和事务处理。 在此之前,它是CORBA。
对SOAP的各种高级扩展,包括安全性和事务处理,都被很多人花费了大量的工作才得以解决。 REST不会在一夜之间发生,而且可能永远不会发生。
我觉得REST目前stream行的很多东西都是对devise不佳和过于复杂的SOAP实现的反弹,这是一个耻辱,因为SOAP不一定是这样的。 与其他任何东西一样,它需要良好的devise才能使其工作得很好。
实际上,REST中的事务的工作原理与传统SOAP服务中的事务处理方式大致相同。
客户端发出一个“开始事务”命令(或者隐式地开始但不提交事务的一些操作),随后是一些附加操作,接着是另一个隐式/显式“结束事务”命令的RPC式事务过时。 很久以前,Web服务的世界已经远离了RPC模型; SOAP中的RPC /编码甚至不符合WS-I标准!
现在的SOAP服务是build立在消息的概念之上的,而不是过程 。 单个消息包含执行完整事务所需的所有信息。 如果您要提交订单, OrderRequest
消息将包含客户信息,订单信息,订单详细信息,付款详细信息…服务器可能需要了解的单个订单的所有信息。
我们确实拥有定义分布式事务语义的WS-Transactions,但是这些并不真正用于支持来自客户端的类似于RPC的语义,当您需要有多个服务参与相同的事务时,它们是用于编排的。 例如,您的订单服务需要征集支付处理服务来validation信用卡信息并发布付款,如果履行服务发现您已经缺货或者类似的东西需要退回付款…您得到的想法。 这一切都发生在服务器环境中,所以在REST中做同样的事情并没有什么阻碍。
在REST中,你有资源而不是消息 ,但这个概念非常相似。 客户端提交( PUT
) Order
资源而不是OrderRequest
消息,资源应包含完成交易所需的所有相同信息。 不可否认,如果您尝试执行复杂的业务stream程,您可能会发现REST与SOAP相比有点笨拙,但这并不意味着您不能继续在前端使用REST,只是SOAP将为您提供更好的服务您的后端服务。
但事实上,99%的时间,人们并不需要WS-Transactions的复杂性。 我知道这一点,因为我几乎全部使用SOAP(WCF),很less使用WS-Transactions。
在REST中,“状态”驻留在客户端上。 服务器告诉客户,“这里是你需要给我创build这个资源的所有信息(完成这个事务)”。 但是这个空白表格实际上并不开始一个事务。 实际提供信息取决于客户 – 填写表格,可以这么说。 客户端在填写表单时的function与服务器无关; 当客户端最终将完成的表单发送到服务器时,将完整地进行validation。 除了客户是跟踪“工作”的人之外,它与工作单元类似。
希望能够更好地了解如何通过REST实现交易。 他们只是依靠更丰富的消息/资源概念和乐观并发的forms。
因为不是每个系统都需要交易。
我知道非常成功的在线会计系统(SaaS),它具有基于REST的非事务性API用于创build,检索和操作发票等。它们广受好评,因为它们的API以及与其他各方整合系统的便利性。 该API易于维护,可在各种平台上使用,并确保向后兼容性合理简单。
缺乏交易可能是一个真正的痛苦,但大多数时候,当他们的服务器没有太多的负载,API的工作得很好。
有时候,不够完美的就够了。
- 在哪里把@Transactional? 在接口规范或实现?
- “transaction.atomic”与“transaction.commit_on_success”相同吗?
- Spring事务中requires_new和嵌套传播的区别
- 有没有更好的方法来检测一个Spring DB事务是否比使用TransactionSynchronizationManager.isActualTransactionActive()有效?
- 事务内的Mysql事务
- TransactionScope和multithreading
- Android数据库交易
- Spring @Transactional属性是否在私有方法上工作?
- 如何debugging在MySQL上超出locking等待超时?