Frage

Ich frage mich, wie Sie den folgenden Anwendungsfall in REST implementieren würden. Ist es überhaupt möglich, ohne das konzeptionelle Modell zu tun?

Lesen oder mehrere Ressourcen im Rahmen einer einzigen Transaktion aktualisieren. Zum Beispiel überträgt $ 100 von Bob Bankkonto in Johns Konto.

Soweit ich sagen kann, ist der einzige Weg, dies zu implementieren ist durch Täuschung. Sie könnten auf die Ressource POST mit zugehörigen entweder John oder Bob und führen den gesamten Betrieb eine einzelne Transaktion. Soweit es mich betrifft dies bricht die REST-Architektur, weil Sie im Wesentlichen einen RPC-Aufruf durch POST statt wirklich, die auf individuellen Ressourcen tunneln.

War es hilfreich?

Lösung

Betrachten wir ein RESTful Warenkorb Szenario. Der Warenkorb ist vom Konzept Ihrer Transaktion Wrapper. In der gleichen Weise, dass Sie mehrere Elemente in einen Warenkorb hinzufügen und dann diesen Korb einreichen, den Auftrag zu bearbeiten, können Sie Bobs Konto Eintrag in die Transaktion Wrapper hinzufügen und dann an den Wrapper Bills Kontoeintrag. Wenn alle Teile vorhanden sind, dann können Sie die Transaktion Wrapper mit allen Teilstücken POST / PUT.

Andere Tipps

Es gibt ein paar wichtigen Fälle, die nicht durch diese Frage beantwortet werden, was meiner Meinung nach zu schlecht ist, weil es eine hohe Platzierung bei Google für die Suchbegriffe hat: -)

Insbesondere wäre ein schönes propertly sein: Wenn Sie zweimal Post (weil einige Cache in der Zwischen hiccupped) Sie nicht den Betrag zweimal übertragen sollte

.

Um dies zu umgehen, eine Transaktion als ein Objekt erstellen. Dies könnte alle Daten enthalten, die Sie bereits kennen, und legen Sie die Transaktion in einem wartenden Zustand.

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

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

Wenn Sie diese Transaktion haben, können Sie es begehen, so etwas wie:

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

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

Beachten Sie, dass mehrere puts an dieser Stelle keine Rolle spielen; sogar ein GET auf dem TXN würde den aktuellen Zustand zurückzukehren. Insbesondere wäre die zweite PUT erkennt, dass die erste bereits in einem entsprechenden Zustand war und es nur zurückkehren - oder, wenn man es in den „rolledback“ Zustand zu bringen versuchen, nachdem sie bereits in „committed“ Zustand ist, würden Sie eine bekommen Fehler, und die tatsächliche engagierte Transaktion zurück.

Solange Sie auf eine einzelne Datenbank oder eine Datenbank mit einer integrierten Transaktionsmonitor sprechen, wird dieser Mechanismus tatsächlich gut funktionieren. Sie könnten zusätzlich Timeouts für Transaktionen einführen, die Sie selbst Header verwendet, könnten auszudrücken Verfallen, wenn man wollte.

In REST Bedingungen, Ressourcen sind Substantive, die mit CRUD werden kann (create / lesen / update / delete) Verben beaufschlagt. Da es kein „Übergangsgeld“ Verb ist, brauchen wir eine „Transaktion“ Ressource zu definieren, die auf mit CRUD gehandelt werden können. Hier ist ein Beispiel in HTTP + POX. Die erste Schritt ist auf CREATE (HTTP POST-Methode) eine neue leer Transaktion:

POST /transaction

Das gibt eine Transaktions-ID, z.B. "1234" und nach URL "/ Transaktionen / 1234". Beachten Sie, dass Brennen dieses POST mehrere Male nicht die gleiche Transaktion mit mehreren IDs erstellen und vermeidet auch Einführung eines „pending“ Zustand. Auch kann POST nicht immer idempotent (a REST-Anforderung), so ist es im Allgemeinen gute Praxis zu minimieren Daten in POSTs.

Sie können die Erzeugung eines Transaktions-ID bis zu dem Client verlassen. In diesem Fall würden Sie POST / Transaktion / 1234 erstellen Transaktion „1234“ und der Server würde einen Fehler zurück, wenn es bereits existiert. In der Fehlerreaktion könnte der Server eine derzeit nicht verwendet ID mit einer entsprechenden URL zurückzukehren. Es ist keine gute Idee, den Server für eine neue ID mit einer GET-Methode abfragen, da GET sollte niemals Server Zustand ändern und das Erstellen / eine neue ID-Reservierung würde Serverstatus ändern.

Als nächstes, we UPDATE (PUT HTTP-Methode), um die Transaktion mit allen Daten, implizit es begehen:

PUT /transaction/1234
<transaction>
  <from>/account/john</from>
  <to>/account/bob</to>
  <amount>100</amount>
</transaction>

Wenn eine Transaktion mit der ID „1234“ vor PUT wurde, der Server eine Fehlermeldung gibt, andernfalls wird eine OK-Antwort und eine URL der abgeschlossene Transaktion anzuzeigen.

NB: in / account / john, "John" sollte eigentlich John einzigartige Kontonummer sein

.

Große Frage ist REST meist mit Datenbank-ähnlichen Beispielen erläutert, wo etwas gespeichert ist, aktualisiert, abgerufen, gelöscht. Es gibt nur wenige Beispiele wie diese, in denen der Server sollten die Daten in irgendeiner Art und Weise verarbeiten. Ich glaube nicht, Roy Fieldings jeder in seiner Dissertation enthalten, die auf http beruhte, nachdem alle.

Aber er über „Representational State Transfer“ als eine Zustandsmaschine, mit Links zu bewegen in dem nächsten Zustand sprechen. Auf diese Weise halten die Dokumente (die Darstellungen) Spur des Kunden Zustand, anstelle des Servers mit, es zu tun. Auf diese Weise gibt es keinen Client-Zustand, nur Zustand in Bezug auf welchen Link Sie sind.

Ich habe darüber nachgedacht, und es scheint mir sinnvoll, dass der Server etwas zu bekommen für Sie zu bearbeiten, wenn Sie laden, würde der Server automatisch zugehörige Ressourcen erstellen, und geben Sie die Links zu ihnen (in der Tat benötigen, wäre es nicht automatisch, sie zu schaffen: es könnte man einfach die Links sagen, und es ihnen nur erstellen, wenn und wenn Sie ihnen folgen - faul Schöpfung). Und auch Sie Links geben erstellen neue bezogenen Ressourcen - eine ähnliche Ressource die gleiche URI hat aber länger (fügt ein Suffix). Zum Beispiel:

  1. Sie laden ( POST ) die Darstellung des Konzepts einer Transaktion mit allen Informationen. Das sieht aus wie ein RPC-Aufruf, aber es ist wirklich die Schaffung von „vorgeschlagen Transaktions resource“. z URI: /transaction Glitches werden mehrere solcher Ressourcen verursachen erstellt, die jeweils mit einer anderen URI werden.
  2. Die Antwort Zustände des Servers der erstellte Ressource URI, seine Darstellung - dazu gehört auch den Link ( URI ), um die damit verbundene Ressource von eine neuen "committed Transaktion Ressource" zu erstellen . andere verwandte Ressourcen sind über die Verknüpfung der vorgeschlagenen Transaktion zu löschen. Dies sind Zustände in der Zustandsmaschine, die der Client folgen kann. Logischerweise ist dies ein Teil der Ressource, die der Client geliefert auf dem Server erstellt, über die Informationen wurde. z URIs: /transaction/1234/proposed, /transaction/1234/committed
  3. Sie POST auf den Link Erstellen Sie die „committed Transaktion Ressource“ , das schafft die Ressource, um den Zustand des Servers zu ändern (die Salden der beiden Konten) **. Mit seiner Art, kann diese Ressource nur einmal erstellt werden und nicht aktualisiert werden kann. Daher Pannen viele Transaktionen zu begehen nicht auftreten können.
  4. Sie können diese beiden Ressourcen bekommen, um zu sehen, was ihr Zustand ist. Unter der Annahme, dass ein POST andere Ressourcen ändern, würde der Vorschlag jetzt als „committed“ (oder vielleicht gar nicht vorhanden) gekennzeichnet werden.

Dies ist ähnlich wie Web-Seiten arbeiten, mit der endgültigen Webseite sagen: „Bist du sicher, dass Sie das tun?“ Die letzte Seite ist selbst eine Darstellung des Status der Transaktion, die einen Link zum nächsten Zustand zu gehen enthält. Nicht nur Finanztransaktionen; auch (zB) Vorschau dann auf wikipedia begehen. Ich denke, der Unterschied in REST ist, dass jede Stufe in der Folge von Zuständen hat einen expliziten Namen (seine URI).

In realen Transaktionen / Vertrieb, gibt es oft unterschiedliche physikalische Dokumente für verschiedene Phasen einer Transaktion (Vorschlag, Bestellung, Empfang usw.). Noch mehr für den Kauf eines Hauses, mit Siedlung etc.

OTOH Das fühlt sich an wie mit Semantik mir spielen; Ich bin unbequem mit der Substantivierung von Verben in Substantive Umwandlung es RESTful zu machen „weil es Substantive (URIs) verwendet anstelle von Verben (RPC-Aufrufe)“. das heißt das Substantiv „committed Transaktions resource“ anstelle des Verbs „commit diese Transaktion“. Ich denke, ein Vorteil der Substantivierung ist man auf die Ressource mit Namen verweisen kann, anstatt sie auf anderer Weise zu spezifizieren, um (wie die Aufrechterhaltung des Sitzungsstatus, so dass Sie wissen, was „die“ Transaktion ist ...)

Aber die wichtige Frage ist: Was sind die Vorteile dieses Ansatzes? d In welche Weise ist dieser REST-Stil besser als RPC-Stil? Ist eine Technik, die für Web-Seiten auch hilfreich für die Verarbeitung von Informationen, über store / retrieve / update / delete toll? Ich denke, dass der entscheidende Vorteil der REST-Skalierbarkeit ist; ein Aspekt, dass braucht nicht explizit Client Zustand zu halten (aber es implizit in der URI der Ressource, und die nächsten Zustände als Links in seiner Darstellung machen). In diesem Sinne hilft es. Vielleicht hilft dies in Schichtung / Pipelining auch? OTOH nur derjenige Benutzer auf ihre spezifischen Transaktion aussehen, also gibt es keinen Vorteil, den es in das Caching, damit andere sie lesen können, den großen Gewinn für http.

Wenn Sie stehen wieder die Diskussion hier zusammenfassen, es ist ziemlich klar, dass REST für viele APIs nicht geeignet ist, insbesondere, wenn die Client-Server-Interaktion von Natur aus Stateful ist, wie es mit nicht-trivialen Transaktionen ist. Warum springt durch alle Reifen vorgeschlagen, für Client und Server beide, um pedantisch einem Prinzip zu folgen, das das Problem nicht passen? Ein besseres Prinzip ist dem Kunden die einfachste, natürlichste, produktive Weise zu komponieren mit der Anwendung zu geben.

Zusammenfassend: Wenn Sie wirklich eine Menge von Transaktionen (Typen, keine Instanzen) in Ihrer Anwendung zu tun, sollten Sie wirklich nicht eine RESTful API werden zu schaffen.

würden Sie haben eine eigene „Transaktions-ID“ Art von tx-Management rollen. So würde es 4 Anrufe werden:

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)

würden Sie haben die Speicherung der Aktionen in einem DB (wenn Lastausgleich) oder im internen Speicher oder so zu handhaben, dann begehen Handling, Rollback-Timeout.

Nicht wirklich einen RESTful Tag im Park.

Ich habe weg für 10 Jahre ab diesem Thema treibt. Kommen wir zurück kann, glaube ich, die Religion nicht als Wissenschaft getarnt, die Sie in waten, wenn Sie Google Rest + zuverlässig. Die Verwirrung ist mythisch.

Ich würde teile diese große Frage in drei:

  • Downstream Services. Jeder Web-Service, den Sie entwickeln nachgelagerten Dienstleistungen, die Sie verwenden, und deren Transaktions Syntax Sie haben keine andere Wahl, als zu folgen. Sie sollten versuchen, und das alles von den Benutzern Ihres Dienstes verstecken, und stellen Sie sicher, dass alle Teile Ihrer Operation erfolgreich war oder als Gruppe scheitern, dann senden Sie das Ergebnis an die Benutzer.
  • Ihre Dienste. Die Kunden wollen eindeutige Ergebnisse zu Web-Service-Anrufen und die üblichen REST Muster POST machen, PUT oder DELETE-Anfragen direkt an materiellen Ressourcen scheinen mich eine schlecht und leicht verbessert, Art und Weise diese Gewissheit zu schaffen. Wenn Sie sich über die Zuverlässigkeit sorgen, müssen Sie Aktionsanforderungen identifizieren. Diese ID kann ein guid auf dem Client oder einen Startwert aus einer relationalen DB auf dem Server erstellt wird, spielt es keine Rolle. Für Server-IDs erzeugt, wird eine Anfrage-Antwort auf den Austausch der ID gewidmet ist. Wenn diese Anforderung fehlschlägt oder die Hälfte erfolgreich ist, kein Problem, wiederholt der Client nur die Anforderung. Nicht verwendetes ids keinen Schaden anrichten.
    Dies ist wichtig, weil es alle nachfolgenden Anforderungen kann voll idempotent sein, in dem Sinne, dass, wenn sie n-mal wiederholt werden sie das gleiche Ergebnis und verursachen nichts weiter geschehen zurückzukehren. Der Server speichert alle Antworten gegen die Wirkung id, und wenn sie die gleiche Anfrage sieht, es Replays die gleiche Antwort. Eine ausführlichere Behandlung des Musters ist in dieser google doc . Der Doc schlägt eine Implementierung, die, wie ich glaube (!), Folgt im Großen und Ganzen REST Prinzipien. Die Experten werden mir sicher sagen, wie es gegen andere. Dieses Muster kann nutzbringend für unsicheren Anruf, um Ihren Web-Service verwendet werden, ob es ist beteiligt Downstream-Transaktionen.
  • Integration Ihres Dienstes in „Transaktionen“ gesteuert durch Vorleistungen. Im Rahmen des Web-Service sind voll ACID-Transaktionen in Betracht gezogen, wie in der Regel nicht die Mühe wert, aber Sie können stark Verbrauchern von Ihrem Service helfen, indem sie abbrechen und / oder Links in der Bestätigungs-Antwort zu bestätigen und damit erreichen? Transaktionen mit Ausgleich .

Ihre Anforderung ist ein Grund. Menschen Lassen Sie sich nicht erzählen Sie Ihre Lösung ist nicht koscher. Richter ihre Architekturen im Lichte, wie gut und wie einfach sie adressieren Ihr Problem.

Vor allem die Übertragung Geld ist nichts, was Sie nicht in einer einzigen Ressource Aufruf tun können. Die Aktion, die Sie tun möchten, ist Geld zu senden. So haben Sie eine Geldtransfer-Ressource auf das Konto des Absenders hinzuzufügen.

POST: accounts/alice, new Transfer {target:"BOB", abmount:100, currency:"CHF"}.

Fertig. Sie brauchen nicht zu wissen, dass dies eine Transaktion, die Atom usw. sein müssen Sie nur aka Geld übertragen. Bitte senden Sie Geld von A nach B.


Aber für die seltenen Fälle, hier eine allgemeine Lösung:

Wenn Sie etwas sehr Komplexes, der viele Ressourcen in einem definierten Zusammenhang mit vielen Einschränkungen tun möchten, dass die tatsächlich durchqueren, was gegen warum Barriere (Business vs. Implementierung Wissen) benötigen Sie Zustand zu übertragen. Da REST staatenlos sein sollten Sie als Kunde brauchen den Staat um zu übertragen.

Wenn Sie Zustand übertragen müssen Sie die Informationen innerhalb von dem Client verstecken. Der Kunde sollte nicht wissen, interne Informationen nur durch die Implementierung benötigt jedoch keine relevanten Informationen in Bezug auf die Geschäftstätigkeit. Wenn diese Informationen in keinen geschäftlichen Wert haben sollte der Staat und eine Metapher wie Token verschlüsselt wird, übergeben oder etwas muß verwendet werden.

So kann ein um einen internen Zustand passieren kann und Verschlüsselung und Signierung das System kann nach wie vor sicher und gesund sein wird. Das Finden der richtige Abstraktion für die Kunden, warum er um Statusinformationen passiert ist etwas, das bis zum Design und Architektur.


Die wirkliche Lösung:

Denken Sie daran, REST spricht HTTP und HTTP kommt mit dem Konzept Cookies zu verwenden. Diese Cookies werden oft vergessen, wenn Leute über REST API und Workflows und Interaktionen über mehrere Ressourcen oder Wünsche sprechen.

Denken Sie daran, was in der Wikipedia über HTTP-Cookies geschrieben:

  

Cookies wurden entwickelt, um ein zuverlässiger Mechanismus zu sein, für Websites Stateful Informationen (wie Artikel in einem Warenkorb) zu erinnern oder des Benutzers Internet-Aktivitäten (einschließlich Klicken auf bestimmte Tasten, die Anmeldung oder die Aufnahme zu erfassen, welche Seiten durch die besucht wurden, Benutzer so weit zurück wie Monate oder Jahre vor).

Also im Grunde, wenn Sie auf Zustand übergeben müssen, ein Cookie verwenden. Es ist für genau den gleichen Grund, es HTTP ist und daher ist es kompatibel zu REST von Design:).


Die bessere Lösung:

Wenn Sie über einen Kunden sprechen einen Workflow mit Beteiligung mehrerer Anforderungen durchgeführt wird man in der Regel über Protokoll sprechen. Jede Form von Protokoll verfügt über eine Reihe von Voraussetzungen für jeden potentiellen Schritt wie führen Sie Schritt A, bevor Sie B tun können.

Das ist natürlich aber aussetzt Protokoll Kunden macht alles komplizierter. Um es einfach zu vermeiden denken, was wir tun, wenn wir komplexe Interaktionen und Dinge in der realen Welt zu tun haben .... Wir verwenden einen Agenten.

den Agenten metapher Sie eine Ressource zur Verfügung stellen können, die alle notwendigen Schritte für Sie ausführen können, und speichern Sie die aktuelle Zuordnung / Anweisungen, um es auf seiner Liste handelt (so können wir POST verwenden, um auf den Agenten oder eine ‚Agentur‘).

Ein komplexes Beispiel:

Der Kauf eines Hauses:

Sie benötigen, um Ihre Glaubwürdigkeit zu beweisen (wie Ihre Vorstrafen Einträge Providing), Sie finanzielle Details benötigen, um sicherzustellen, müssen Sie das eigentliche Haus mit einem Anwalt und ein vertrauenswürdigen Dritten kaufen, um die Mittel zu speichern, stellen Sie sicher, dass das Haus jetzt gehört Sie den Kauf Zeug zu Ihrer Steuersätze usw. und fügen Sie (nur als Beispiel, können einige Schritte falsch oder was auch immer sein).

Diese Schritte könnten mehrere Tage dauern abgeschlossen werden, können einige parallel usw. durchgeführt werden.

Um dies zu tun, geben Sie nur das Mittel die Aufgabe Kauf Haus wie:

POST: agency.com/ { task: "buy house", target:"link:toHouse", credibilities:"IamMe"}.

Fertig. Die Agentur sendet Ihnen Verbindung einen Verweis zurück, dass Sie den Status dieser Arbeit zu sehen und verfolgen können und der Rest wird automatisch durch die Agenten der Agentur durchgeführt.

Denken Sie an einem Bug-Tracker zum Beispiel. Grundsätzlich berichten Sie den Fehler und die Fehler-ID, was los ist zu überprüfen, verwenden. Du kannstverwendet auch einen Dienst zu Änderungen dieser Ressource zu hören. Mission Fertig.

Ich denke, dass es völlig akzeptabel in diesem Fall ist die reine Theorie von REST in dieser Situation zu brechen. Auf jeden Fall glaube ich nicht, es ist tatsächlich etwas in REST, die sagt, dass Sie nicht abhängigen Objekte in Business Cases, die es erfordern berühren kann.

Ich glaube wirklich, es lohnt sich nicht, die zusätzlichen Reifen Sie durch einen benutzerdefinierten Transaktionsmanager erstellen springen würde, wenn Sie nur die Datenbank, es zu tun nutzen könnte.

Sie müssen nicht Server-Seite Transaktionen in REST verwenden.

Einer des REST contraints:

  

Stateless

     

Die Client-Server-Kommunikation weiter durch keinen Client-Kontext eingeschränkt wird auf dem Server zwischen Anfragen gespeichert. Jede Anforderung von jedem Client enthält alle notwendigen Informationen, die Anforderung zu, und jeder Sitzungsstatus in dem Client gehalten wird.

Der einzige RESTful Weg ist, um eine Transaktion Redo-Log zu erstellen und sie in den Client-Zustand versetzt. Mit den Anforderungen sendet der Client die Redo-Log und der Server nachvollzieht die Transaktion und

  1. setzt die Transaktion zurück, sondern bietet eine neue Transaktion Redo log (einen Schritt weiter)
  2. oder schließlich die Transaktion abzuschließen.

Aber vielleicht ist es einfacher, eine Server-Session-basierte Technologie zu verwenden, die Server-Seite Transaktionen unterstützt.

Ich glaube, dass der Fall der Verwendung eine eindeutige Kennung auf dem Client erzeugt werden würde, um sicherzustellen, dass die Verbindung Schluckauf nicht in einer Duplizität impliziert durch die API gespeichert.

Ich denke, eine Client generierte GUID-Feld unter Verwendung zusammen mit dem Transferobjekt und sicherzustellen, dass die gleiche GUID nicht wieder wieder eingesetzt wurde wäre eine einfachere Lösung für die Banküberweisung Angelegenheit sein.

Sie wissen nicht, über komplexere Szenarien, wie zum Beispiel mehr Flugtickets buchen oder Mikroarchitekturen.

fand ich ein Papier über das Thema, beziehen die Erfahrungen von Umgang mit die Transaktion Unteilbarkeit in RESTful Services .

Im einfachen Fall (ohne verteilte Ressourcen), können Sie die Transaktion als eine Ressource in Erwägung ziehen könnten, in dem die Handlung es schaffen, das Ende Ziel erreicht.

So übertragen zwischen <url-base>/account/a und <url-base>/account/b, könnten Sie folgendes <url-base>/transfer schreiben.

<transfer>
    <from><url-base>/account/a</from>
    <to><url-base>/account/b</to>
    <amount>50</amount>
</transfer>

Dies würde eine neue Transfer Ressource und gibt die neue URL der Übertragung erstellen -. Zum Beispiel <url-base>/transfer/256

Im Moment des erfolgreichen Posts, dann die ‚echte‘ Transaktion wird auf dem Server ausgeführt wird, und die Menge von einem Konto und zu einem anderen entfernt.

Dies ist jedoch erstreckt sich nicht auf eine verteilte Transaktion (wenn, sagen wir ‚a‘ auf einer Bank hinter einem Dienst gehalten wird, und ‚b‘ wird bei einer anderen Bank hinter einem anderen Dienst gehalten) - anders als zu sagen: „versuchen Begriff alle Operationen in einer Weise, die „nicht verteilte Transaktionen erfordern.

Ich denke, man könnte die TAN in der URL / Ressource enthalten:

  1. PUT / Transaktion die ID zu erhalten (zum Beispiel "1")
  2. [PUT, GET, POST, was auch immer] / 1 / Konto / bob
  3. [PUT, GET, POST, was auch immer] / 1 / Konto / Rechnung
  4. DELETE / Transaktion mit der ID 1

Nur eine Idee.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top