Ich frage mich, wie Sie den folgenden Anwendungsfall in REST implementieren würden. Ist es überhaupt möglich, auf das konzeptionelle Modell zu verzichten?
Lesen oder aktualisieren Sie mehrere Ressourcen im Rahmen einer einzelnen Transaktion. Überweisen Sie beispielsweise 100 USD von Bobs Bankkonto auf Johns Konto.
Soweit ich das beurteilen kann, ist die einzige Möglichkeit, dies umzusetzen, das Betrügen. Sie können auf die mit John oder Bob verknüpfte Ressource POSTEN und den gesamten Vorgang mit einer einzigen Transaktion ausführen. Für mich bricht dies die REST-Architektur, da Sie im Wesentlichen einen RPC-Aufruf über POST tunneln, anstatt wirklich mit einzelnen Ressourcen zu arbeiten.
Es gibt einige wichtige Fälle, die von dieser Frage nicht beantwortet werden, was ich für schade halte, da sie bei Google einen hohen Rang für die Suchbegriffe hat :-)
Konkret wäre eine nette Eigenschaft: Wenn Sie zweimal POSTEN (weil ein Cache in der Zwischenzeit einen Schluckauf hat), sollten Sie den Betrag nicht zweimal überweisen.
Um dies zu erreichen, erstellen Sie eine Transaktion als Objekt. Dies könnte alle Daten enthalten, die Sie bereits kennen, und die Transaktion in einen ausstehenden Zustand versetzen.
Sobald Sie diese Transaktion abgeschlossen haben, können Sie sie wie folgt festschreiben:
Beachten Sie, dass mehrere Puts an dieser Stelle keine Rolle spielen. Sogar ein GET auf dem TXN würde den aktuellen Status zurückgeben. Insbesondere erkennt der zweite PUT, dass sich der erste bereits im entsprechenden Status befindet, und gibt ihn einfach zurück. Wenn Sie versuchen, ihn in den Status "Rollback" zu versetzen, nachdem er sich bereits im Status "Festgeschrieben" befindet, erhalten Sie einen Fehler und die tatsächlich festgeschriebene Transaktion zurück.
Solange Sie mit einer einzelnen Datenbank oder einer Datenbank mit integriertem Transaktionsmonitor sprechen, funktioniert dieser Mechanismus tatsächlich einwandfrei. Sie können zusätzlich Zeitüberschreitungen für Transaktionen einführen, die Sie sogar mit Expires-Headern ausdrücken können, wenn Sie möchten.
quelle
In REST-Begriffen sind Ressourcen Substantive, auf die mit CRUD-Verben (Erstellen / Lesen / Aktualisieren / Löschen) reagiert werden kann. Da es kein Verb "Geld überweisen" gibt, müssen wir eine "Transaktions" -Ressource definieren, auf die mit CRUD reagiert werden kann. Hier ist ein Beispiel in HTTP + POX. Der erste Schritt besteht darin, eine neue leere Transaktion zu erstellen (HTTP-POST-Methode) :
Dies gibt eine Transaktions-ID zurück, z. B. "1234" und die entsprechende URL "/ transaction / 1234". Beachten Sie, dass durch mehrmaliges Auslösen dieses POST nicht dieselbe Transaktion mit mehreren IDs erstellt wird und auch die Einführung eines "ausstehenden" Status vermieden wird. Außerdem kann POST nicht immer idempotent sein (eine REST-Anforderung). Daher ist es im Allgemeinen empfehlenswert, Daten in POSTs zu minimieren.
Sie können die Generierung einer Transaktions-ID dem Client überlassen. In diesem Fall würden Sie POST / transaction / 1234, um die Transaktion "1234" zu erstellen, und der Server würde einen Fehler zurückgeben, wenn dieser bereits vorhanden ist. In der Fehlerantwort könnte der Server eine derzeit nicht verwendete ID mit einer entsprechenden URL zurückgeben. Es ist keine gute Idee, den Server mit einer GET-Methode nach einer neuen ID abzufragen, da GET den Serverstatus niemals ändern sollte und das Erstellen / Reservieren einer neuen ID den Serverstatus ändern würde.
Als nächstes aktualisieren wir die Transaktion mit allen Daten (PUT HTTP-Methode) und legen sie implizit fest:
Wenn eine Transaktion mit der ID "1234" zuvor PUT war, gibt der Server eine Fehlerantwort aus, andernfalls eine OK-Antwort und eine URL, um die abgeschlossene Transaktion anzuzeigen.
NB: In / account / john sollte "john" wirklich Johns eindeutige Kontonummer sein.
quelle
Gute Frage, REST wird meistens mit datenbankähnlichen Beispielen erklärt, in denen etwas gespeichert, aktualisiert, abgerufen, gelöscht wird. Es gibt nur wenige Beispiele wie dieses, bei denen der Server die Daten auf irgendeine Weise verarbeiten soll. Ich glaube nicht, dass Roy Fielding irgendetwas in seine These aufgenommen hat, die schließlich auf http basierte.
Aber er spricht von "repräsentativem Zustandstransfer" als Zustandsmaschine, wobei Verbindungen zum nächsten Zustand übergehen. Auf diese Weise verfolgen die Dokumente (die Darstellungen) den Clientstatus, anstatt dass der Server dies tun muss. Auf diese Weise gibt es keinen Client-Status, sondern nur den Status, auf dem Sie sich befinden.
Ich habe darüber nachgedacht, und es erscheint mir vernünftig, dass der Server beim Hochladen automatisch verwandte Ressourcen erstellt und Ihnen die Links zu diesen gibt, um den Server dazu zu bringen, etwas für Sie zu verarbeiten (tatsächlich würde dies nicht der Fall sein) Sie müssen nicht automatisch erstellt werden: Sie können nur die Links anzeigen und sie nur erstellen, wenn und wenn Sie ihnen folgen (verzögerte Erstellung). Und um Ihnen auch Links zum Erstellen neuer verwandter Ressourcen zu geben - eine verwandte Ressource hat denselben URI, ist jedoch länger (fügt ein Suffix hinzu). Beispielsweise:
/transaction
Störungen werden mehrere solcher Ressourcen mit jeweils einer anderen URI erstellt./transaction/1234/proposed
,/transaction/1234/committed
Dies ähnelt der Funktionsweise von Webseiten. Auf der letzten Webseite steht "Sind Sie sicher, dass Sie dies tun möchten?". Diese endgültige Webseite ist selbst eine Darstellung des Status der Transaktion, die einen Link zum nächsten Status enthält. Nicht nur Finanztransaktionen; auch (zB) Vorschau dann auf Wikipedia festschreiben. Ich denke, der Unterschied in REST besteht darin, dass jede Stufe in der Folge von Zuständen einen expliziten Namen (ihren URI) hat.
Bei realen Transaktionen / Verkäufen gibt es häufig unterschiedliche physische Dokumente für verschiedene Phasen einer Transaktion (Angebot, Bestellung, Quittung usw.). Noch mehr für den Kauf eines Hauses, mit Siedlung etc.
OTOH Das fühlt sich für mich an, als würde ich mit Semantik spielen. Ich bin unzufrieden mit der Nominalisierung der Konvertierung von Verben in Substantive, um sie RESTful zu machen, "weil Substantive (URIs) anstelle von Verben (RPC-Aufrufen) verwendet werden". dh das Substantiv "festgeschriebene Transaktionsressource" anstelle des Verbs "diese Transaktion festschreiben". Ich denke, ein Vorteil der Nominalisierung besteht darin, dass Sie die Ressource nach Namen referenzieren können, anstatt sie auf andere Weise angeben zu müssen (z. B. um den Sitzungsstatus beizubehalten, damit Sie wissen, was "diese" Transaktion ist ...).
Die wichtige Frage ist jedoch: Was sind die Vorteile dieses Ansatzes? dh Inwiefern ist dieser REST-Stil besser als der RPC-Stil? Ist eine Technik, die sich hervorragend für Webseiten eignet, auch für die Verarbeitung von Informationen hilfreich, die über das Speichern / Abrufen / Aktualisieren / Löschen hinausgehen? Ich denke, dass der Hauptvorteil von REST die Skalierbarkeit ist. Ein Aspekt davon ist, dass der Client-Status nicht explizit beibehalten werden muss (sondern dass er implizit im URI der Ressource und im nächsten Status als Links in ihrer Darstellung enthalten sein muss). In diesem Sinne hilft es. Vielleicht hilft das auch beim Layering / Pipelining? OTOH nur der eine Benutzer wird sich seine spezifische Transaktion ansehen, daher ist es nicht vorteilhaft, sie zwischenzuspeichern, damit andere sie lesen können, der große Gewinn für http.
quelle
Wenn Sie sich zurückziehen, um die Diskussion hier zusammenzufassen, ist es ziemlich klar, dass REST für viele APIs nicht geeignet ist, insbesondere wenn die Client-Server-Interaktion von Natur aus statusbehaftet ist, wie dies bei nicht trivialen Transaktionen der Fall ist. Warum sollten Sie für Client und Server durch alle vorgeschlagenen Rahmen springen, um pedantisch einem Prinzip zu folgen, das nicht zum Problem passt? Ein besseres Prinzip besteht darin, dem Kunden die einfachste, natürlichste und produktivste Möglichkeit zu geben, mit der Anwendung zu komponieren.
Zusammenfassend lässt sich sagen, dass Sie keine RESTful-API erstellen sollten, wenn Sie wirklich viele Transaktionen (Typen, keine Instanzen) in Ihrer Anwendung ausführen.
quelle
Ich habe mich 10 Jahre lang von diesem Thema entfernt. Wenn ich zurückkomme, kann ich nicht glauben, dass sich die Religion als Wissenschaft tarnt, in die Sie sich stürzen, wenn Sie google rest + zuverlässig sind. Die Verwirrung ist mythisch.
Ich würde diese allgemeine Frage in drei Teile teilen:
Dies ist wichtig, da dadurch alle nachfolgenden Anforderungen vollständig idempotent sind, in dem Sinne, dass sie, wenn sie n-mal wiederholt werden, dasselbe Ergebnis zurückgeben und nichts weiter bewirken. Der Server speichert alle Antworten anhand der Aktions-ID. Wenn dieselbe Anforderung angezeigt wird, wird dieselbe Antwort erneut abgespielt. Eine ausführlichere Beschreibung des Musters finden Sie in diesem Google-Dokument . Das Dokument schlägt eine Implementierung vor, die meines Erachtens (!) Im Großen und Ganzen den REST-Prinzipien folgt. Experten werden mir sicherlich sagen, wie es andere verletzt. Dieses Muster kann für jeden unsicheren Aufruf Ihres Webdienstes verwendet werden, unabhängig davon, ob es sich um nachgelagerte Transaktionen handelt oder nicht.
Ihre Anforderung ist grundlegend. Lassen Sie sich nicht sagen, dass Ihre Lösung nicht koscher ist. Beurteilen Sie ihre Architekturen anhand dessen, wie gut und wie einfach sie Ihr Problem angehen.
quelle
Sie müssten Ihre eigene "Transaktions-ID" -Typ-Verwaltung durchführen. Es wären also 4 Anrufe:
Sie müssten die Speicherung der Aktionen in einer Datenbank (bei Lastenausgleich) oder im Speicher oder dergleichen durchführen und dann Commit, Rollback und Timeout durchführen.
Kein wirklich ruhiger Tag im Park.
quelle
Ich denke, dass es in diesem Fall völlig akzeptabel ist, die reine Theorie von REST in dieser Situation zu brechen. Auf jeden Fall glaube ich nicht, dass es in REST tatsächlich etwas gibt, das besagt, dass Sie abhängige Objekte in Geschäftsfällen, die dies erfordern, nicht berühren können.
Ich denke wirklich, dass es die zusätzlichen Rahmen nicht wert ist, durch die Sie springen würden, um einen benutzerdefinierten Transaktionsmanager zu erstellen, wenn Sie einfach die Datenbank dafür nutzen könnten.
quelle
Zuallererst ist das Überweisen von Geld nichts, was Sie nicht in einem einzigen Ressourcenaufruf tun können. Die Aktion, die Sie ausführen möchten, ist das Senden von Geld. Sie fügen dem Konto des Absenders eine Geldtransferressource hinzu.
Getan. Sie müssen nicht wissen, dass dies eine Transaktion ist, die atomar sein muss usw. Sie überweisen einfach Geld aka. Senden Sie Geld von A nach B.
Aber für die seltenen Fälle hier eine allgemeine Lösung:
Wenn Sie etwas sehr Komplexes tun möchten, das viele Ressourcen in einem definierten Kontext mit vielen Einschränkungen umfasst, die tatsächlich die Was-gegen-Warum-Barriere (Geschäfts- oder Implementierungswissen) überschreiten, müssen Sie den Status übertragen. Da REST zustandslos sein sollte, müssen Sie als Client den Status übertragen.
Wenn Sie den Status übertragen, müssen Sie die darin enthaltenen Informationen vor dem Client verbergen. Der Kunde sollte keine internen Informationen kennen, die nur für die Implementierung benötigt werden, aber keine geschäftsrelevanten Informationen enthalten. Wenn diese Informationen keinen geschäftlichen Wert haben, sollte der Status verschlüsselt und eine Metapher wie Token, Pass oder etwas verwendet werden.
Auf diese Weise kann man den internen Status weitergeben und mithilfe von Verschlüsselung und Signatur kann das System immer noch sicher und solide sein. Die richtige Abstraktion für den Kunden zu finden, warum er Statusinformationen weitergibt, hängt vom Design und der Architektur ab.
Die wirkliche Lösung:
Denken Sie daran, dass REST über HTTP spricht und HTTP mit dem Konzept der Verwendung von Cookies geliefert wird. Diese Cookies werden häufig vergessen, wenn über die REST-API sowie über Workflows und Interaktionen gesprochen wird, die sich über mehrere Ressourcen oder Anforderungen erstrecken.
Denken Sie daran, was in der Wikipedia über HTTP-Cookies geschrieben steht:
Wenn Sie also den Status weitergeben müssen, verwenden Sie ein Cookie. Es wurde aus genau dem gleichen Grund entwickelt, es ist HTTP und daher von Natur aus mit REST kompatibel :).
Die bessere Lösung:
Wenn Sie über einen Client sprechen, der einen Workflow mit mehreren Anforderungen ausführt, sprechen Sie normalerweise über das Protokoll. Jede Form von Protokoll enthält eine Reihe von Voraussetzungen für jeden möglichen Schritt, z. B. Schritt A ausführen, bevor Sie B ausführen können.
Dies ist natürlich, aber das Aussetzen des Protokolls für Clients macht alles komplexer. Um dies zu vermeiden, denken Sie einfach darüber nach, was wir tun, wenn wir komplexe Interaktionen und Dinge in der realen Welt ausführen müssen. Wir benutzen einen Agenten.
Mithilfe der Agentenmetapher können Sie eine Ressource bereitstellen, die alle erforderlichen Schritte für Sie ausführen und die tatsächliche Zuweisung / Anweisung, auf die sie reagiert, in ihrer Liste speichern kann (sodass wir POST für den Agenten oder eine 'Agentur' verwenden können).
Ein komplexes Beispiel:
Ein Haus kaufen:
Sie müssen Ihre Glaubwürdigkeit nachweisen (z. B. die Bereitstellung Ihrer Polizeiaufzeichnungen), Sie müssen finanzielle Details sicherstellen, Sie müssen das eigentliche Haus mit einem Anwalt und einem vertrauenswürdigen Dritten kaufen, der die Gelder aufbewahrt, überprüfen, ob das Haus Ihnen gehört und Fügen Sie das Kaufmaterial Ihren Steuerunterlagen usw. hinzu (nur als Beispiel können einige Schritte falsch sein oder was auch immer).
Diese Schritte können mehrere Tage dauern, einige können parallel ausgeführt werden usw.
Um dies zu tun, geben Sie dem Agenten einfach die Aufgabe Haus kaufen wie folgt:
Getan. Die Agentur sendet Ihnen eine Referenz zurück, mit der Sie den Status dieses Auftrags anzeigen und verfolgen können. Der Rest wird automatisch von den Agenten der Agentur erledigt.
Denken Sie zum Beispiel an einen Bug-Tracker. Grundsätzlich melden Sie den Fehler und können anhand der Fehler-ID überprüfen, was los ist. Sie können sogar einen Dienst verwenden, um Änderungen dieser Ressource abzuhören. Mission erledigt.
quelle
Sie dürfen in REST keine serverseitigen Transaktionen verwenden.
Eine der REST-Einschränkungen:
Die einzige RESTful-Methode besteht darin, ein Transaktions-Redo-Protokoll zu erstellen und es in den Client-Status zu versetzen. Mit den Anforderungen sendet der Client das Redo-Protokoll und der Server wiederholt die Transaktion und
Aber vielleicht ist es einfacher, eine auf Serversitzungen basierende Technologie zu verwenden, die serverseitige Transaktionen unterstützt.
quelle
Ich glaube, dass dies der Fall wäre, wenn eine eindeutige Kennung verwendet würde, die auf dem Client generiert wird, um sicherzustellen, dass der Verbindungsfehler nicht zu einer von der API gespeicherten Duplizität führt.
Ich denke, die Verwendung eines vom Client generierten GUID-Felds zusammen mit dem Überweisungsobjekt und die Sicherstellung, dass dieselbe GUID nicht erneut eingefügt wurde, wäre eine einfachere Lösung für die Überweisungssache.
Sie kennen keine komplexeren Szenarien wie die Buchung mehrerer Flugtickets oder Mikroarchitekturen.
Ich fand ein Papier zu diesem Thema, in dem die Erfahrungen im Umgang mit der Transaktionsatomarität in RESTful-Diensten beschrieben wurden .
quelle
Im einfachen Fall (ohne verteilte Ressourcen) können Sie die Transaktion als Ressource betrachten, bei der der Vorgang des Erstellens das Endziel erreicht.
Um zwischen
<url-base>/account/a
und zu übertragen<url-base>/account/b
, können Sie Folgendes an posten<url-base>/transfer
.Dies würde eine neue Übertragungsressource erstellen und beispielsweise die neue URL der Übertragung zurückgeben
<url-base>/transfer/256
.Im Moment der erfolgreichen Veröffentlichung wird dann die "echte" Transaktion auf dem Server ausgeführt und der Betrag von einem Konto entfernt und einem anderen hinzugefügt.
Dies gilt jedoch nicht für eine verteilte Transaktion (wenn beispielsweise 'a' bei einer Bank hinter einem Dienst und 'b' bei einer anderen Bank hinter einem anderen Dienst gehalten wird) - außer zu sagen: "Versuchen Sie, alle zu formulieren." Operationen auf eine Weise, die keine verteilten Transaktionen erfordert ".
quelle
Ich denke, Sie könnten die TAN in die URL / Ressource aufnehmen:
Nur eine Idee.
quelle