Herunterfahren einer VM über eine REST-Schnittstelle
Dies ist tatsächlich ein ziemlich berühmtes Beispiel, das 2009 von Tim Bray angeführt wurde .
Roy Fielding, der das Problem diskutierte, teilte diese Beobachtung :
Ich persönlich bevorzuge Systeme, die den überwachten Status (wie den Energiestatus) als nicht bearbeitbar behandeln.
Kurz gesagt, Sie haben eine Informationsressource, die eine aktuelle Darstellung des überwachten Zustands zurückgibt. Diese Darstellung kann einen Hypermedien-Link zu einem Formular enthalten , das eine Änderung dieses Status anfordert, und das Formular verfügt über einen weiteren Link zu einer Ressource, die (jede) Änderungsanforderung verarbeitet.
Seth Ladd hatte die wichtigsten Einsichten in das Problem
Wir haben Running von einem einfachen Zustand einer Person zu einem echten Nomen gemacht, das erstellt, aktualisiert und besprochen werden kann.
Führen Sie dies zurück, um die Computer neu zu starten. Ich würde argumentieren, dass Sie nach / vdc / 434 / cluster / 4894 / server / 4343 / reboots POSTEN würden. Sobald Sie gepostet haben, haben Sie einen URI, der diesen Neustart darstellt, und Sie können ihn für Statusaktualisierungen abrufen. Durch die Magie des Hyperlinks wird die Darstellung des Neustarts mit dem Server verknüpft, der neu gestartet wird.
Ich denke, URI-Speicherplatz zu prägen ist billig und URIs sind noch billiger. Erstellen Sie eine Sammlung von Aktivitäten, die als Substantive und als POST, PUT und DELETE away modelliert sind!
RESTvolles Programmieren ist Vogons Bürokratie im Webmaßstab. Wie macht man etwas RESTful? Erfinde dafür neue Papiere und digitalisiere die Papiere.
In einer etwas ausgefalleneren Sprache definieren Sie das Domänenanwendungsprotokoll für "Herunterfahren einer VM" und identifizieren die Ressourcen, die Sie zum Anzeigen / Implementieren dieses Protokolls benötigen
Schauen Sie sich Ihre eigenen Beispiele an
PATCH /api/virtualmachines/42
Content-Type:application/json
{ "state": "shutting down" }
Das ist ok; Sie behandeln die Anfrage selbst nicht wirklich als separate Informationsressource, können sie aber dennoch verwalten.
Sie haben ein wenig in Ihrer Darstellung der Änderung verpasst.
Mit PATCH enthält die beigefügte Entität jedoch eine Reihe von Anweisungen, die beschreiben, wie eine Ressource, die sich derzeit auf dem Ursprungsserver befindet, geändert werden sollte, um eine neue Version zu erstellen.
Der JSON-Patch- Medientyp formatiert beispielsweise Anweisungen, als ob Sie ein JSON-Dokument direkt ändern würden
[
{ "op": "replace", "path": "state", "value": "shutting down" }
]
In Ihrer Alternative ist die Idee nah, aber nicht offensichtlich richtig. PUT
ist eine vollständige Ersetzung des Status der Ressource in der Ziel-URL , sodass Sie wahrscheinlich keine Schreibweise wählen würden, die wie eine Sammlung aussieht, als Ziel einer Darstellung einer einzelnen Entität.
POST /api/virtualmachines/42/actions
Stimmt mit der Fiktion überein, dass wir eine Aktion an eine Warteschlange anhängen
PUT /api/virtualmachines/42/latestAction
Steht im Einklang mit der Fiktion, dass wir das Endelement in der Warteschlange aktualisieren; Es ist ein bisschen komisch, das so zu machen. Das Prinzip der geringsten Überraschung empfiehlt, jedem PUT eine eigene eindeutige Kennung zuzuweisen, anstatt sie alle an einem Ort zu platzieren und mehrere Ressourcen gleichzeitig zu ändern.
Beachten Sie, dass es REST im Hinblick auf die Schreibweise von URI-REST egal ist. /cc719e3a-c772-48ee-b0e6-09b4e7abbf8b
ist für REST ein perfekter URI. Die Lesbarkeit ist wie bei Variablennamen ein besonderes Anliegen. Die Verwendung von Schreibweisen, die mit RFC 3986 übereinstimmen , macht die Menschen viel glücklicher.
CQRS
Was ist, wenn wir eine CQRS-Domäne mit vielen solchen "Aktionen" (auch als Befehle bezeichnet) haben, die möglicherweise zu Aktualisierungen mehrerer Aggregate führen oder nicht auf CRUD-Operationen für konkrete Ressourcen und Subressourcen abgebildet werden können?
Greg Young über CQRS
CQRS ist ein sehr einfaches Muster, das viele Möglichkeiten für eine Architektur eröffnet, die es sonst möglicherweise nicht gibt. CQRS ist keine eventuelle Konsistenz, es ist kein Eventing, es ist kein Messaging, es gibt keine getrennten Modelle zum Lesen und Schreiben und es wird auch kein Event-Sourcing verwendet.
Wenn die meisten Leute über CQRS sprechen, sprechen sie wirklich über das Anwenden des CQRS-Musters auf das Objekt, das die Dienstgrenze der Anwendung darstellt.
Angesichts der Tatsache, dass Sie im Kontext von HTTP / REST über CQRS sprechen, ist es vernünftig anzunehmen, dass Sie in diesem letzteren Kontext arbeiten. Lassen Sie uns also fortfahren.
Dieser ist überraschenderweise sogar einfacher als Ihr vorheriges Beispiel. Der Grund dafür ist einfach: Befehle sind Nachrichten .
Jim Webber beschreibt HTTP als das Anwendungsprotokoll eines Büros aus den 1950er Jahren. Die Arbeit wird erledigt, indem Nachrichten entgegengenommen und in den Posteingang gestellt werden. Die gleiche Idee gilt - wir erhalten eine leere Kopie eines Formulars, füllen es mit den uns bekannten Einzelheiten aus und liefern es aus. Ta da
Sollten wir versuchen, so viele Befehle wie möglich zu modellieren, die mit Concrete erstellt oder auf konkreten Ressourcen aktualisiert werden (gemäß dem ersten Ansatz aus Beispiel I), und im Übrigen "Aktionsendpunkte" verwenden?
Ja, sofern es sich bei den "konkreten Ressourcen" eher um Nachrichten als um Entitäten im Domänenmodell handelt.
Schlüsselidee: Ihre REST-API ist immer noch eine Schnittstelle . Sie sollten in der Lage sein, das zugrunde liegende Modell zu ändern, ohne dass Clients die Nachrichten ändern müssen. Wenn Sie ein neues Modell freigeben, geben Sie eine neue Version Ihrer Web-Endpunkte frei, die wissen, wie Sie Ihr Domänenprotokoll verwenden und auf das neue Modell anwenden.
Passt ein CQRS-Modell besser zu einer RPC-ähnlichen API?
Nicht wirklich - insbesondere Web-Caches sind ein hervorragendes Beispiel für ein "schließlich konsistentes Lesemodell". Indem Sie jede Ihrer Ansichten unabhängig adressierbar machen und dabei jeweils eigene Caching-Regeln festlegen, erhalten Sie eine Reihe kostenloser Skalierungsfunktionen. Es gibt relativ wenig Anziehungskraft auf einen exklusiven RPC-Ansatz zum Lesen.
Für Schreibvorgänge ist dies eine schwierige Frage: Das Senden aller Befehle an einen einzelnen Handler an einem einzelnen Endpunkt oder an eine einzelne Familie von Endpunkten ist mit Sicherheit einfacher . Bei REST geht es mehr darum, wie Sie feststellen, dass sich der Endpunkt auf dem Client befindet.
Das Behandeln einer Nachricht als eine eigene, eindeutige Ressource hat den Vorteil, dass Sie PUT verwenden können, und macht die zwischengeschalteten Komponenten darauf aufmerksam, dass die Behandlung der Nachricht idempotent ist, sodass sie in bestimmten Fällen der Fehlerbehandlung teilnehmen können . (Hinweis: Wenn die Ressourcen aus Sicht der Clients unterschiedliche URIs aufweisen, handelt es sich um unterschiedliche Ressourcen. Die Tatsache, dass möglicherweise alle denselben Anforderungsbehandlungscode auf dem Ursprungsserver haben, ist ein Implementierungsdetail, das von der Uniform verborgen wird Schnittstelle).
Fielding (2008)
Ich sollte auch bemerken, dass das oben Genannte noch nicht vollständig RESTful ist, zumindest wie ich den Begriff benutze. Alles, was ich getan habe, ist die Beschreibung der Serviceschnittstellen, die nicht mehr sind als jeder RPC. Um es REST-fähig zu machen, müsste ich Hypertext hinzufügen, um den Service einzuführen und zu definieren, zu beschreiben, wie das Mapping mithilfe von Formularen und / oder Link-Vorlagen durchgeführt wird, und Code bereitstellen, um die Visualisierungen auf nützliche Weise zu kombinieren.