Nach dem Buch REST vs Too Many Requests

8

Aus Roy Fieldings Kommentar zu seinem eigenen Artikel, in dem gefälschte REST-Apis entschlüsselt werden :

Eine wirklich RESTful API sieht aus wie Hypertext. Jede adressierbare Informationseinheit trägt eine Adresse, entweder explizit (z. B. Link- und ID-Attribute) oder implizit (z. B. abgeleitet von der Medientypdefinition und Repräsentationsstruktur). Abfrageergebnisse werden durch eine Liste von Links mit zusammenfassenden Informationen dargestellt, nicht durch Arrays von Objektdarstellungen (die Abfrage ist kein Ersatz für die Identifizierung von Ressourcen).

Dies bedeutet, dass Sie, wenn Sie beispielsweise eine Liste der 100 zuletzt angemeldeten Benutzer abfragen und deren Namen und E-Mails anzeigen müssen, zunächst eine GETAbfrage nach der Ergebnisliste durchführen müssen, die (im Wesentlichen) eine Liste von Verknüpfungselementen sein, wobei jedes Verknüpfungsobjekt den URI einer Benutzerressource enthält. Sie müssten dann 100 weitere GET Anfragen stellen - eine für jede Benutzerressource -, bevor Sie tatsächlich über die Daten verfügen, die Sie zur Anzeige Ihrer Ergebnisse benötigen.

Das scheint unglaublich ineffizient. Gibt es wirklich keinen anderen wirklich REST-fähigen Weg, um die Daten zu erhalten, die Sie in 1 oder 2 Anfragen benötigen?

Jona
quelle
1
Haben Sie den Teil "mit zusammenfassenden Informationen" nicht verpasst?
Luc Franken
1
Ich habe es nicht verpasst, aber "zusammenfassende Informationen" bedeuten für mich "Zusammenfassung", nicht "alle Daten". Er sagt ausdrücklich "nicht durch Arrays von Objektdarstellungen" - genau das brauchen wir für unsere Anzeige.
Jonah
1
Wir sehen die Liste als Ressource und für uns enthält sie Felder wie: Link zu einer einzelnen Ressource, Titel, Kurzbeschreibung und Anzahl der Kommentare zum Beispiel. Wir schließen keine vollständigen Objekte ein, da diese viel zu groß sind. Unsere Listenressourcen liefern also alle Informationen, die für die Verwendung erforderlich sind. Wenn Sie mehr möchten, laden Sie die gesamte Ressource, die Formulare, viele Inhalte und andere größere Teile enthalten kann. Wir haben einmal versucht, alle Ressourcen (YAGNI-Denkprozess) vollständig einzubeziehen, aber das ist zusammengebrochen. Also haben wir diesen Schritt hinzugefügt. Und ich denke, es ist vollständig REST, eine Liste von Informationen ist eine Ressource für sich.
Luc Franken
Versuchen Sie nicht, (blind) Fielding-Sätze über REST strikt anzuwenden. Natürlich ist er der Vater der REST-Architektur, aber seien Sie vorsichtig: Die REST-Architektur ist für hochskalierbare Systeme gedacht, deshalb wurde sie aus dem Web abgeleitet. Wenn es sinnvoll ist, ein Array von Objekten für Leistungsprobleme zu verwenden, wählen Sie es aus.
AilurusFulgens
HAL + json wird allgemein als RESTful angesehen. Es enthält sowohl eine abgespeckte Version (Zusammenfassung) der Objekte als auch einen Link zur vollständigen Ressource.
RubberDuck

Antworten:

7

Gibt es wirklich keinen anderen wirklich REST-fähigen Weg, um die Daten zu erhalten, die Sie in 1 oder 2 Anfragen benötigen?

  • Nicht wirklich
  • Aber überleg es dir nicht

Wenn Sie an REST denken, denken Sie wie üblich daran, dass es eine Referenzimplementierung (das World Wide Web) gibt, gegen die Sie prüfen können.

Betrachten Sie das Amazon-Portal. Wenn ich dieses Lesezeichen mit einem leeren Cache öffne, stellt mein Browser Anforderungen an 275 Ressourcen.

Würde ich eine bessere Latenz erhalten, wenn der gesamte Status in einer einzigen Nutzlast abgerufen würde? Ja.

Würde es skalieren? würde es im Web skalieren? Wahrscheinlich nicht. Das sind 4,5 MB Daten, die nicht freigegeben werden können, da sie 1 KB enthalten, die für mein Profil spezifisch sind. Wenn meine Kollegin am Schreibtisch neben mir auch zu Amazon geht, zieht sie dieselben Daten über das Netzwerk.

Zerlegen Sie diese Nutzdaten in individuell adressierbare Ressourcen, und plötzlich wird es viel besser - wir erhalten jeweils noch 1 KB Personalisierung, und wir haben jeweils noch unsere lokal zwischengespeicherte Kopie der 4,5 MB, aber wir mussten das Netzwerk nicht knallen Dies ist schwierig, da die meisten unserer Anfragen von einem lokalen gemeinsam genutzten Cache bearbeitet wurden und nicht über das Internet weitergeleitet werden mussten.

Denken Sie auch daran, dass Sie nicht wirklich ein Problem mit mehreren Ressourcen haben , sondern ein Problem mit mehreren Anforderungen . Dies kann mithilfe von HTTP / 2.0-Push-Versprechungen verringert werden, indem der Server proaktiv Darstellungen pusht, die zwischengespeichert werden können. Vielleicht - ein zustandsloser Server weiß nicht, was der Client zwischengespeichert hat, und TLS schlägt vor, dass das Zwischenspeichern bei Zwischenprodukten keine Priorität hat ...

Dies bedeutet, dass Sie, wenn Sie beispielsweise eine Liste der 100 zuletzt angemeldeten Benutzer abfragen und deren Namen und E-Mails anzeigen müssen, zunächst eine GET-Abfrage für die Ergebnisliste durchführen müssen, was (im Wesentlichen) der Fall wäre ) eine Liste von Verknüpfungselementen sein, wobei jedes Verknüpfungsobjekt den URI einer Benutzerressource enthält. Sie müssten dann 100 weitere GET-Anforderungen stellen - eine für jede Benutzerressource -, bevor Sie tatsächlich über die Daten verfügen, die Sie zur Anzeige Ihrer Ergebnisse benötigen.

Wenn Sie dies in HTML tun würden, wäre Ihre Darstellung der zuletzt angemeldeten Benutzer wahrscheinlich ein Dokument mit einer Liste oder einer Tabelle mit Namen, E-Mail-Adressen und Links zu diesen Ressourcen. Ta-da.

Verlieren Sie diese Beobachtung durch Fielding nicht aus den Augen.

Das bedeutet nicht, dass ich denke, jeder sollte seine eigenen Systeme nach dem REST-Architekturstil entwerfen. REST ist für langlebige netzwerkbasierte Anwendungen gedacht, die mehrere Organisationen umfassen. Wenn Sie keine Notwendigkeit für die Einschränkungen sehen, verwenden Sie sie nicht.

BEARBEITEN

Kann ich das gleiche Argument für eine JSON-Darstellung vorbringen? Wenn die betreffende Ressource "100 zuletzt angemeldete Benutzer" ist und nicht das Ergebnis einer parametrisierten Abfrage, kann ich dann die Daten selbst anstelle von Ressourcenverknüpfungen zurückgeben? wenn nicht, warum? Warum unterscheidet sich JSON in dieser Hinsicht wesentlich von HTML?

Wie sie sich ähneln: Wenn Sie mehr Daten in die "Ergebnisliste" packen, sparen Sie die Kosten für zusätzliche Anforderungen und beeinträchtigen gleichzeitig die Skalierung. Der spezifische Medientyp, den Sie für die Darstellung verwenden, spielt keine Rolle - zumindest soweit ich weiß.

Wie sie sich unterscheiden: HTML ist ein Hypermedia-Format und JSON nicht - jede Standard-Client-Implementierung, die mit der HTML-Spezifikation vertraut ist, weiß, wie man die Links in einem HTML-Dokument findet, das Optionen wie das Vorabrufen unterstützt. JSON verfügt nicht über diese Standardisierung. Sie benötigen Out-of-Band-Informationen zur Datenstruktur, um zu verstehen, wo sich die Links in einer JSON-Darstellung befinden. HAL wäre in dieser Hinsicht eine engere Übereinstimmung mit HTML; Der Hauptunterschied zwischen HAL und HTML ist die Übernahme. HTML hat einen Vorsprung von 20 Jahren?

Für zusätzliche Einblicke können Sie auch das Atom-Syndication-Format überprüfen , das sowohl Einträge als auch Feeds (Listen von Einträgen) beschreibt, insbesondere die Regeln für atom: entry , auf die über eine eigenständige Ressource oder über eine Feed-Ressource zugegriffen werden kann.

VoiceOfUnreason
quelle
1
Dieser letzte Absatz von Fielding sollte im umgekehrten Text auf die Stirn aller REST-Pedanten geschrieben sein, damit sie ihn jedes Mal sehen können, wenn sie in den Spiegel schauen.
Robert Harvey
tolle Antwort wie immer. Betreff: Ihr letzter Absatz zu einer HTML-Darstellung. Kann ich dasselbe Argument für eine JSON-Darstellung vorbringen? Wenn die betreffende Ressource "100 zuletzt angemeldete Benutzer" ist und nicht das Ergebnis einer parametrisierten Abfrage, kann ich dann die Daten selbst anstelle von Ressourcenverknüpfungen zurückgeben? wenn nicht, warum? Warum unterscheidet sich JSON in dieser Hinsicht wesentlich von HTML?
Jonah
@Jonah JSON ist kein Hypermedia-Format, im Gegensatz zu HTML (und einigen anderen). Ein Hypermedia-Format ermöglicht die Beschreibung von Links und Beziehungen. In HTML tun Sie dies zum Beispiel mit <a href="URI" rel="">und <form method="post">. In JSON können Sie nicht, wenn Sie es in eine Ad - hoc - Weise zu verwenden, weil JSON definiert nichts über hypermedia (einige Beispiele für Ad-hoc - Hypermedia - Nutzung in JSON: _link : [ ... ], links : [ ... ] , _link_ : [ ... ], etc.) (PS: große Antwort)
AilurusFulgens
@AilurusFulgens, klar, ich hätte genauer sein sollen. Ich meinte so etwas wie "hal + json" (oder ein anderes JSON-basiertes Hypermedia-Format) - der Kern der Frage ist der gleiche: Warum ist es in Ordnung, ein "Dokument" in HTML mit allen Daten zurückzugeben, aber nicht Machen Sie dasselbe in einem JSON-basierten Hypermedia-Format?
Jonah
danke für die bearbeitung. Um sicherzustellen, dass ich Sie verstehe, würden Sie, wenn Sie alle Ergebnisse in einer HTML-Tabelle zurückgeben würden, anstatt einen <ul>anklickbaren Link anzugeben, die Skalierung genauso gefährden, als ob Sie das Äquivalent in einer hal + json-Antwort getan hätten? Insbesondere würde eine solche Antwort nicht so gut skaliert werden, da die zurückgegebenen Ergebnisse, die sich vermutlich häufig ändern, nicht zwischengespeichert werden können. Während eine Liste von Links weniger Daten enthält, ist der nicht zwischenspeicherbare Teil kleiner? Ist das die Idee oder fehlt mir noch mehr?
Jonah