Lorsque vous examinez REST l'une des premières choses que tout le monde remarquera probablement, c'est qu'aucune sémantique de transaction n'est définie, certains disent que cela est implicitement contraire à ce qui est REST is , tandis que d'autres disent que toute tentative de le faire entraînerait une "altération" des systèmes REST.
Mais disons pour les arguments que REST est devenu un choix 'api' populaire, et chaque site de l'univers a commencé à exposer des points d'entrée reposants.
Comment sont-ils exactement utilisables sans comportement de transaction (et je parle de non-compensation)? car il me semble que l'un des avantages de REST est qu'il décompose les composants des données, cela pourrait les ouvrir à la possibilité pour les clients intelligents de composer des données (et d'ajouter et d'ajuster ces données composées) mais si je ne peux pas apporter mes modifications à cette composition de données de manière atomique et isolée, l'utilisation de REST devient inutile).
Au fur et à mesure que le temps passe et que le besoin d'une exposition sérieuse des données arrive, nous allons vouloir quelque chose qui soit: Simple (REST y gagne) et prend en charge le comportement transactionnel afin que nous puissions manipuler ces données de manière fiable.
Maintenant, j'ai lu un argument spécifique à quelques reprises dans ma recherche, et son lien avec la façon dont nous sommes censés penser les transactions dans REST, et l'exemple donné est le panier d'achat, où vous avez implicitement un isolement parce que le panier C'est le tien.
Cependant, je ne suis pas d'accord avec cet argument, premièrement, l'isolement d'un panier d'achat est simplement pratique, ce n'est pas un isolement de transaction .. que se passe-t-il si je fais simultanément une opération contre mon panier pendant qu'une partie de mon application lit des données à partir de cela? Je ne m'attendrais pas à ce que la partie lecture de mon application voit des données "toujours en transaction".
Sans parler du fait que toutes les modifications de données n'ont pas un modèle de transaction implicite, les transactions sur plusieurs services n'en ont certainement pas.
Il me semble que les transactions doivent se produire, et doivent se produire de manière à permettre aux appels réels REST d'être ignorants du fait (ajouter au reste de la charge utile étant un gros non non, mais l'ajout d'en-têtes étant OK).
J'ai lu quelques suggestions sur la façon dont un modèle de transaction peut être créé via REST, et certaines des spécifications écrites semblent être très récentes.
Y a-t-il de véritables réflexions à ce sujet? ne devrait-il pas y avoir quelque chose de "plus" que REST afin que la nature simpliste de REST puisse être exploitée contre la manipulation de données solides (transactions "acides").
Si ce n'est pas le cas, est-ce qu'on s'attend à vraiment faire monter la barre et dire aux développeurs de services que s'ils veulent interagir dans un monde de données pur, ils doivent prendre en charge quelque chose sans doute monolithique comme le savon? ou pire encore, essayer de construire leur propre support de transaction personnalisé dans quelque chose comme REST, rendant chaque service non standard et brisant toute la puissance de REST?
Merci d'avance pour toute réflexion.
Modifier, ajouté un bref scénario:
Imaginez un formulaire client qui gère la création d'un album, pour plus de commodité sur cet album, plutôt que de demander à l'utilisateur de donner l'URI pour la ressource d'artiste, ils peuvent choisir parmi une liste d'artistes (très probablement OBTENIR du catalogue d'artistes) .
Par souci de convivialité, le client peut écrire le nom de l'artiste manuellement afin de pouvoir créer un artiste "en ligne". Dans le scénario de publication, le code client le comprend, et avant d'envoyer la demande de création de l'album, il essaie d'abord de déterminer si l'artiste existe déjà, si c'est le cas, obtient l'uri pour cet artiste, sinon crée l'artiste et obtient l'uri des artistes.
Le code client continue ensuite de créer l'album, c'est le client le plus intelligent que d'habitude, il n'est pas assis juste au-dessus de REST et publication 'dumbly', mais a plutôt une interaction qui gère la logique REST plus pure.
Cependant, dans ce scénario, il serait agréable de garantir que l'artiste n'est pas créé à moins que l'album ne le soit, étant donné que l'artiste est créé en premier.
Ce n'est pas aussi "critique" qu'une transaction l'impliquerait, mais cela définit un ensemble de travaux que le code client préférerait se produire en une seule opération (après tout, il IS ce qui rend ce look) comme une seule opération pour l'utilisateur).
Le seul conseil que j'ai vu pour ce scénario est de demander au client d'effectuer une action de compensation en cas d'échec de la création de l'album, et d'appeler spécifiquement pour supprimer l'artiste. Mais cela semble problématique, car le client suppose que l'artiste a été isolé, aussi improbable que cela puisse être, que se passe-t-il si un autre client a déjà "vu" cet artiste et lui assigne?
Ce sont mes préoccupations concernant la modification des données, et bien qu'il y ait certainement d'autres lacunes (qui dit que l'artiste ne peut pas être simplement supprimé à une date ultérieure de toute façon), ces actions ne sont PAS transparentes (c.-à-d., Les actions ne sont pas quelque chose d'automatisé par client, mais quelque chose qu'un utilisateur a spécifiquement demandé).
J'espère que cela aide à éclairer le sujet.
Je vais supposer que lorsque vous parlez de transactions, vous parlez d'un protocole Two Phase Commit distribué.
Si je comprends bien, vous essayez de comprendre comment nous pourrions jamais utiliser REST pour effectuer des opérations qui s'étendent sur plusieurs systèmes si REST ne peut pas prendre en charge les transactions sur différents REST requêtes. Le problème est que vous faites l'hypothèse potentiellement erronée que nous devrions utiliser les transactions pour assurer la cohérence. Quel prix payons-nous pour les utiliser et quelles alternatives existent?
Pat Helland qui travaillait pour Amazon et est maintenant chez Microsoft, a écrit un article Life Beyond Distributed Transactions . Dans l'article, l'auteur fait la déclaration suivante:
Malheureusement, les programmeurs qui s'efforcent de résoudre des objectifs commerciaux tels que le commerce électronique, la gestion de la chaîne d'approvisionnement, les applications financières et de santé doivent de plus en plus penser à évoluer sans transactions distribuées. Ils le font parce que les tentatives d'utilisation des transactions distribuées sont trop fragiles et fonctionnent mal.
Son article explore des solutions alternatives aux transactions distribuées qui évoluent et fonctionnent bien.
Peut-être que REST réussira car il ne prend pas en charge les transactions. Voici une citation de Roy Fielding, le gars qui a inventé le terme REST
Si vous avez besoin d'un protocole de transaction distribué, comment pouvez-vous dire que votre architecture est basée sur REST? Je ne vois tout simplement pas comment vous pouvez passer d'une situation (d'utiliser l'état d'application RESTful sur le client et l'hypermédia pour déterminer toutes les transitions d'état) à la situation suivante d'avoir besoin d'un accord distribué de sémantique de transaction dans lequel le client doit dire au serveur comment gérer ses propres ressources.
... pour l'instant je considère la "transaction de repos" comme un oxymore.
Ceci provient d'un message sur la liste de discussion REST du 9 juin 2009. Je ne peux pas fournir de lien car les groupes Yahoo sont inutiles.
Si vous voulez des transactions dans une application ReST, à la fonction API ReST, c'est généralement parce que vous avez toujours votre google technicien webservice sur Google.
Regardons les choses autrement.
Savonnez-vous sur: Ouvrez une transaction, créez un enregistrement client, créez un enregistrement de commande, validez la transaction.
Google ReST sur: demandez au serveur quoi faire. Le serveur dit "créer une ressource client", donc POST/clients. Le serveur dit "maintenant, créez une commande si vous le souhaitez", le client crée la commande en suivant le formulaire.
Dans ReST, le protocole d'application est exprimé en termes de ressources créées et manipulées, et non en termes de données qui ont des limites de transaction.
Si vous voulez avoir une transaction de longue durée qui couvre toutes ces opérations, c'est le serveur qui décide de l'initier, pas le client.
Vous pouvez toujours implémenter des transactions de longue durée côté serveur. Si vous essayez de vouloir des transactions du côté client, vous supposez que le client connaît déjà toutes les opérations qu'il va exécuter et les limites des transactions qui existent entre ces opérations. Si c'est ce que vous attendez du client, vous avez déjà renoncé à la nature contraignante et hypermédia d'une architecture de repos.
Donc, en effet, si vous ne faites pas de ReST et essayez d'intégrer RPC sur http, vous aurez un problème avec l'absence de transactions.
Je pense que la plupart des actions qui nécessitent normalement des transactions peuvent être retravaillées pour se produire sans elles.
Par exemple, le virement bancaire classique. Supposons que je veuille déplacer 100 $ du compte A vers B:
Commencer la transaction /Débit A, 100 $ /Crédit B, 100 $ Valider la transaction
Cela pourrait être retravaillé comme suit:
/Transfert A, B, 100 $
De cette façon, le serveur peut effectuer cette opération en deux étapes, mais l'action du client est une opération atomique unique qui a un sens logique.
Je suis sûr qu'il existe de nombreux exemples où il est plus pratique de faire un ensemble d'opérations en tout ou rien (et je suis curieux de savoir ce que les gens peuvent trouver pour les résoudre), mais je retravaille généralement les choses de cette manière.
Une opération REST peut démarrer une transaction, effectuer plusieurs opérations de base de données ou d'autres opérations transactionnelles, puis valider ou annuler - le tout dans le cadre d'une transaction.
Ce que REST ne peut pas faire, c'est être autre que la racine d'une transaction. Vous ne pouvez pas démarrer une transaction, puis effectuer deux REST opérations et une opération de base de données) , puis validez-les tous ensemble. C'est comme la situation des services Web ASMX dans .NET. Ils peuvent être à l'origine d'une transaction, mais c'est tout. Ils ont réussi pendant des années, jusqu'à ce que WCF soit introduit, prenant en charge WS-Transactions. aujourd'hui et à l'aide de WCF, la plupart des opérations de service Web n'ont pas besoin d'être transactionnelles dans le sens que vous demandez.
Je pense que les transactions utilisant REST sont réellement réalisables. Considérez une transaction comme une ressource que vous pouvez créer (démarrer), éditer (publier les modifications via) et supprimer (valider, annuler). Les modifications publiées dans la transaction n'auraient pas besoin de modifier l'état global tant que la transaction n'a pas été validée, et pendant la validation, vous pourriez appliquer les règles de cohérence d'état globales dont vous auriez besoin. La ressource de transaction serait, bien sûr, protégée par règles d'autorisation.
Vous avez déjà mentionné l'illustration courante de ce concept:
Maintenant, j'ai lu un argument spécifique à quelques reprises dans ma recherche, et son lien avec la façon dont nous sommes censés penser les transactions dans REST, et l'exemple donné est le panier d'achat, où vous avez implicitement un isolement parce que le panier C'est le tien.
Cependant, je ne suis pas d'accord avec cet argument, premièrement, l'isolement d'un panier d'achat est simplement pratique, ce n'est pas un isolement de transaction .. que se passe-t-il si je fais simultanément une opération contre mon panier pendant qu'une partie de mon application lit des données à partir de cela? Je ne m'attendrais pas à ce que la partie lecture de mon application voit des données "toujours en transaction".
Pourquoi ne permettez-vous pas la visualisation de la transaction? Tant que vous le présentez tel qu'il est, une liste des modifications en attente, il est en fait utile de fournir cette fonctionnalité. Mais si vous ne voulez pas qu'il soit visible, vous pouvez désactiver GET
sur la ressource.
C'est un sujet intéressant. Comme vous l'avez mentionné, SOAP possède déjà ce type de fonctionnalité, mais il a fallu de nombreuses années avant SOAP mûri au point où les gens envisageraient de faire de la sécurité et des transactions réelles) Avant cela, c'était CORBA.
Les diverses extensions de haut niveau de SOAP, y compris la sécurité et les transactions, ont demandé beaucoup de travail à de nombreuses personnes pour les corriger. Cela n'arrivera pas à REST du jour au lendemain, et cela pourrait ne jamais arriver du tout.
Je pense qu'une grande partie de la popularité actuelle de REST est une sorte de réaction contre les implémentations mal conçues et trop compliquées SOAP, ce qui est dommage, car SOAP doesn pas comme ça. Comme pour toute autre chose, il a besoin d'un bon design pour bien fonctionner.
Jetez un oeil à OpenStreetMap API . Je pense que c'est une sorte de "REST" et qu'il fournit une sorte de "transactions" - appelées "changesets" là-bas. Est-ce ce dont vous avez besoin?
En fait, les transactions en REST fonctionnent de la même manière que les transactions ( sont censées fonctionner en traditionnel SOAP services.
Les transactions de style RPC, où le client émet une commande "begin transaction" (ou une opération qui commence implicitement mais ne valide pas de transaction), suivies de quelques opérations supplémentaires, suivies d'une autre commande implicite/explicite "end transaction", sont désuètes . Le monde des services Web s'est éloigné du modèle RPC il y a longtemps; RPC/encodé en SOAP n'est même pas compatible WS-I!
Au lieu de procédures, SOAP d'aujourd'hui sont construits autour du concept de messages. Un seul message contient toutes toutes les informations nécessaires pour effectuer une transaction complète. Si vous soumettez une commande, le message OrderRequest
contiendra les informations sur le client, les informations sur la commande, les détails de la commande, les détails du paiement ... tout ce que le serveur pourrait avoir besoin de savoir sur une seule commande.
Nous avons des transactions WS qui définissent la sémantique des transactions distribuées, mais elles ne sont pas vraiment destinées à prendre en charge la sémantique de type RPC du client, elles sont destinées aux orchestrations lorsque vous devez faire participer plusieurs services à la même transaction. Par exemple, votre service de commande doit faire appel à un service de traitement des paiements pour valider les informations de carte de crédit et publier un paiement, qui doit être annulé si le service d'exécution constate que vous êtes en rupture de stock, ou quelque chose comme ça ... vous avoir l'idée. Tout cela se déroule dans l'environnement du serveur, donc rien ne vous empêche vraiment de faire la même chose dans REST.
Dans REST, vous avez des ressources au lieu de messages , mais le concept est vraiment assez similaire. Au lieu d'un message OrderRequest
, le client soumet (PUT
) une ressource Order
, et la ressource doit contenir toutes les mêmes informations nécessaires pour terminer la transaction. Certes, si vous essayez d'effectuer des orchestrations complexes, vous pourriez trouver REST un peu lourd par rapport à SOAP, mais cela ne signifie pas que vous ne pouvez pas continuer à utiliser REST pour votre front-end , juste que SOAP vous servira mieux pour votre services back-end .
La réalité, cependant, est que 99% du temps, les gens n'ont pas besoin de la complexité de WS-Transactions. Je le sais car j'utilise SOAP (WCF) presque exclusivement et utilise rarement WS-Transactions.
Dans REST, "l'état" réside sur le client. Le serveur dit au client: "voici toutes les informations que vous devez me donner pour créer cette ressource (terminer cette transaction)". Mais ce formulaire vierge ne commence pas réellement une transaction. C'est au client de fournir les informations - remplissez le formulaire, pour ainsi dire. Ce que le client fait pendant qu'il remplit le formulaire ne concerne pas le serveur; lorsque le client envoie enfin le formulaire terminé au serveur, celui-ci est validé dans son intégralité. C'est semblable à une unité de travail, sauf que le client est celui qui garde la trace du "travail".
J'espère que cela donne une meilleure idée de la façon dont les transactions peuvent être et sont réalisées via REST. Ils s'appuient simplement sur un concept de message/ressource plus riche et une forme de concurrence optimiste.
Parce que tous les systèmes ne nécessitent pas de transactions.
Je connais des systèmes de comptabilité en ligne (SaaS) très performants qui ont une API non transactionnelle basée sur REST pour créer, récupérer et manipuler des factures, etc. Ils sont largement acclamés pour leur API et la facilité d'intégration de leur système avec d'autres parties. L'API est facile à entretenir, utilisable à partir d'une variété de plates-formes et assurer une compatibilité descendante est relativement simple.
L'absence de transactions peut être très pénible, mais la plupart du temps, lorsque leurs serveurs ne sont pas trop chargés, l'API fonctionne très bien.
Parfois, moins que parfait est juste assez bon.